目录
1. 封装
把传感器功能封装在模块
新建.c 和.h文件
添加头文件和格式
然后,在 void CountSensor_Init(void) 函数中配置外部中断
外部中断配置步骤
a.配置RCC,打开外部时钟
b.配置GPIO,端口选择输入模式
c.配置AFIP,选择用到的GPIO,连接到EXTI
e.配置EXTI,选择边沿触发方式
f.配置NVIC,给中断的选择合适的优先级
最后通过NVIC,外部中断信号进入CPU
开启RCC时钟怎么理解?
举例来说就是:
RCC是总电闸室
APB2是其中一条电路线
GPIOB是3楼B房间
开启时钟就是让电工(RCC)把3楼B房间(GPIOB)的电闸合上,才能通电
为什么总线要分APB1/APB2?
就像高速公路分快慢车道:
APB2:高速车道(挂GPIO、高速外设)
APB1:普通车道(挂定时器、串口等)
2. 配置外部中断
2.1 开启RCC、AFIO时钟
//开启RCC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//开启AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
EXTI、NVIC外设的时钟一直处于打开状态,不用再打开
2.2 配置GPIO(和前几章步骤一样)
//配置GPIO
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);
2.3 配置AFIO外部中断引脚选择
库函数在GPIO中
了解一下AFIO的配置(gpio.h)
GPIO_PinRemapConfig进行引脚重映射
GPIO_EXTILineConfig配置AFIO的数据选择器,选择想要的中断引脚
这里用到GPIO_EXTILineConfig,右键跳转定义,选择参数
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
2.4 配置EXTI(exti.h)
EXTI_DeInit 清除配置,恢复上电默认的状态
EXTI_Init 配置外设
EXTI_StructInit 参数传递的结构体变量赋值一个默认值
EXTI_GenerateSWInterrupt 软件触发外部中断
EXTI_GetFlagStatus 获取指定的标志位是否被置1
EXTI_ClearFlag 对置1的标志位清除
EXTI_GetITStatus 获取中断标志位是否被置1
EXTI_ClearITPendingBit 清除中断挂起标志位
调用 EXTI_Init,右键跳转定义,复制结构体类型名字 EXTI_InitTypeDef
起变量名 EXTI_InitStructure,“.”引出结构体成员
EXTI_Line,指定配置的中断线,右键跳转定义
ctrl+f搜索,选择EXTI_Line14
另外几个结构体一样的操作
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);
2.5 配置NVIC(misc.h)
一样的操作,这里省略
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);
2.6 中断程序
点开启动文件md.s,以IRQHandler结尾的字符串就是中断函数的名字
复制EXTI15_10_IRQHandler,中断函数无参无返回值
void EXTI15_10_IRQHandler(void)
然后进行中断标志位的判断
到exti.h里复制EXTI_GetITStatus,跳转参数
判断返回值是不是 = = SET
中断程序结束后,调用清除中断标志位的函数,只有中断标志位置为1,程序会跳转到中断函数,如果不清除中断标志位,就会一直申请中断,程序卡死在中断函数里
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line14) == SET)
{
EXTI_ClearITPendingBit(EXTI_Line14);
}
}
然后测试是否能进入中断
初始化函数在头文件中声明,中断函数不用声明,它是自动执行的
main.c文件
2.7 统计中断触发的次数
定义变量
中断函数加入CountSensor_Count ++;并返回变量,头文件声明
CountSensor.h文件
在main.c文件里,循环调用OLED_ShowNum,显示计次的数据
CountSensor.c 全部代码
#include "stm32f10x.h" // Device header
uint16_t CountSensor_Count;
void CountSensor_Init(void)
{
//开启RCC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//开启AFIO时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//配置GPIO
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);
//配置AFIO
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
//配置EXTI
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
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);
}
}
太忙了,好久没学习了,挤出时间终于把文章写完了,如果对你有帮助的话点个免费的关注和赞吧!