编写外部中断EXTI代码:以【对射式红外传感器计次】为例
![](https://img-blog.csdnimg.cn/51b42fba77004046a837c03a23d32d08.png)
配置外部中断时从左至右参考该图流程
1、完成驱动文件导入操作和编写驱动程序基本代码(参考之前文章)
2、在CountSensor.c中初始化函数CountSensor_Init
void CountSensor_Init(void){/*第一步:配置RCC,把涉及到的外设时钟打开*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//打开GPIOB的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//打开AFIO的时钟(AFIO也是APB2的外设)/*还有EXTI和NVIC两个外设的时钟需要打开,但因为这两个外设的时钟一直都是打开的,所以不需要配置开启*//*第二步:配置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);//初始化GPIOB/*第三步:配置AFIO,选择使用的中断引脚*//*ST公司并未分配专门的库函数文件给AFIO,AFIO的库函数存放在GPIO中*/GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);//配置AFIO的数据选择器,选中需要的中断引脚/*第四步:配置EXTI,选择中断配置各种模式*/EXTI_InitTypeDef EXTI_InitStructure;EXTI_InitStructure.EXTI_Line = EXTI_Line14;//指定要配置的中断线EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//指定外部中断线的模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//指定触发信号的有效边沿EXTI_InitStructure.EXTI_LineCmd = ENABLE;//指定选择的中断线的新状态EXTI_Init(&EXTI_InitStructure);//初始化EXTI/*第五步:配置NVIC,选择中断配置各种模式*//*NVIC是内核外设,库函数被ST公司分配到杂项mics.h文件中*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//在配置中断之前先指定NVIC中断分组NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;//指定中断通道来开启或关闭//IRQn_Type的定义在stm32f10x.h文件中//选择使用芯片的中断通道列表(STM32F10X_MD)NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//指定中断通道是使能还是失能NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;//指定所选通道的抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//指定所选通道的响应优先级NVIC_Init(&NVIC_InitStructure);//初始化NVIC}
3、在CountSensor.c中编写中断服务程序函数EXTI15_10_IRQHandler
在STM32中,中断函数的名字都是固定的,每个中断通道都对应一个中断函数(名字参考启动文件startup_stm32f10x_md.s)
文件中以IRQHandler结尾的字符串就是中断函数的名字
中断函数都是无参无返回值的
void EXTI15_10_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line14) == SET)//中断标志位判断,确定由哪个中断源触发看看EXTI14的中断标志位是不是1(EXTI15~10都能进来,判断是不是EXTI14进来的){if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0){CountSensor_Count ++;}EXTI_ClearITPendingBit(EXTI_Line14);//中断程序结束后,清除中断标志位}}
4、在CountSensor.c中编写传感器返回端口值获取函数CountSensor_Get
//先定义一个全局变量uint16_t CountSensor_Count;uint16_t CountSensor_Get(void){return CountSensor_Count;}
5、在CountSensor.h中声明初始化函数CountSensor_Init和返回端口值获取函数CountSensor_Get
void CountSensor_Init(void);uint16_t CountSensor_Get(void);//中断函数不用声明,因为中断函数不需要调用,会自动执行
6、在主程序main.c中#include "CountSensor.h"
#include "CountSensor.h"
7、在主循环之前先初始化外部中断
![](https://img-blog.csdnimg.cn/906f3f3b0c3a498482538894d05dc4d0.png)
8、在主循环中编写程序主体
int main(void){OLED_Init();CountSensor_Init();OLED_ShowString(1,1,"Count:");while(1){OLED_ShowNum(1,7,CountSensor_Get(),5);}}
实现功能:OLED显示屏默认显示Count:00000,挡一次对射式红外传感器Count+1
(可改变中断触发方式:上升沿触发、下降沿触发、双边触发)