5-2对射式红外传感器计数&旋转编码器计数
系列文章目录
前言
本章主要是学习STM32F103系列的EXTI(Extern Interrupt)外部中断,本次实验用到的传感器用按键替代。
一、对射式红外传感器计数
本意是传感器两边的红外线遮住一次,拿开就计数一次,我这里就直接按键按一次,计数就加一次。
1.原理图

图1.1.1 对射式红外传感器计数原理图
2.代码
CountSensor.c : 对射式红外传感器驱动函数,驱动的是如图1.1.1所示的PB14口
#include "stm32f10x.h" // Device header
uint16_t CountSensor_Count;
void CountSensor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line14;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
}
uint16_t CountSensor_Get(void)
{
return CountSensor_Count;
}
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line14) == SET)
{
CountSensor_Count++;
EXTI_ClearITPendingBit(EXTI_Line14);
}
}
CountSensor.h:头文件声明函数(中断函数不需要声明和调用,中断时自己会执行)(中断有对应特定的函数名在启动文件(/Start/startup_stm32f10x_md.s)里面寻找,直接复制粘贴,比较不会出错,函数名如果错了,就进不了中断)
#ifndef __COUNTSENSOR_H__
#define __COUNTSENSOR_H__
void CountSensor_Init(void);
uint16_t CountSensor_Get(void);
#endif
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"
int main(void)
{
OLED_Init();
CountSensor_Init();
OLED_ShowString(1, 1, "Count:");
while(1)
{
OLED_ShowNum(1, 7, CountSensor_Get(), 5);
}
}
3运行结果
下降沿触发中断
运行时PB14口为高电平,按下按键后变低电平,Count++
图1.3.1 执行前

图1.3.2 按键按下后
二、旋转编码器计数
1.原理图
遵循和UP主用的一样的GPIO口,GPIOB_Pin_0,GPIOB_Pin_1。

图2.1.1 旋转编码器计数
2.代码
代码如下(示例):
Encoder.c
#include "stm32f10x.h" // Device header
int16_t Encoder_Count;
void Encoder_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&NVIC_InitStructure);
}
int16_t Encoder_Get(void)
{
int16_t Temp;
Temp = Encoder_Count;
Encoder_Count = 0;
return Temp;
}
void EXTI0_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line0) == SET)
{
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
{
Encoder_Count--;
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
void EXTI1_IRQHandler(void){
if (EXTI_GetITStatus(EXTI_Line1) == SET)
{
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
{
Encoder_Count++;
}
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
因为GPIOB_Pin_0,GPIOB_Pin_1的中断函数名不同,分别为EXTI0_IRQHandler,EXTI1_IRQHandler。所以是分开的两个中断函数。
如果中断函数名相同的只要写一个就可以了。例如:
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line14) == SET)
{
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
{
Encoder_Count--;
}
EXTI_ClearITPendingBit(EXTI_Line14);
}
if (EXTI_GetITStatus(EXTI_Line15) == SET)
{
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_15) == 0)
{
Encoder_Count++;
}
EXTI_ClearITPendingBit(EXTI_Line15);
}
}

图2.2.1 启动文件中的中断函数名参考
3.运行结果

图2.3.1 启动时

图2.3.2 按键1按下数值减1

图2.3.3 按键2按下数值加1
总结
仿真毕竟比不上真实硬件,硬件很多执行器,传感器都是封装好的,目前还不会PCB,在以后的文章中我会简化电路,但原理是一样的。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)