以下代码是一个“对射式红外传感器计次”,实现的功能是,通过隔档对射式红外传感器,产生中断,在中断中计数(显示在OLED上),本篇以此代码,大致了解下STM32中断代码编写的方式。
#include "stm32f10x.h" // Device header
uint16_t CountSensor_Count = 0;
void CountSensor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitTypeDef InitTypeStruct;
InitTypeStruct.GPIO_Mode = GPIO_Mode_IPU;
InitTypeStruct.GPIO_Pin = GPIO_Pin_14;
InitTypeStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &InitTypeStruct);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line14;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStruct);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStruct);
}
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);
}
}
解析:
1. 打开外设 GPIOB/AFIO 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
打开外设 GPIOB/AFIO 时钟
RCC: Reset and Clock Control 复位和时钟控制,用于配置处理器的时钟系统和复位功能。
AFIO: Alternate Function I/O 复用功能输入输出,因为这里是将 B14 既作为 GPIO 的输入,又作为中断的中断信号的输出,所以这里需要复用 B14 这个引脚。即,B14 既是有普通 GPIO 功能,又有中断功能。
2. 配置通用 GPIO
GPIO_InitTypeDef InitTypeStruct;
InitTypeStruct.GPIO_Mode = GPIO_Mode_IPU;
InitTypeStruct.GPIO_Pin = GPIO_Pin_14;
InitTypeStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &InitTypeStruct);
配置 GPIOB PIN14 (PB14) 为上拉输入
GPIO_Mode:管脚工作方式:
typedef enum
{ GPIO_Mode_AIN = 0x0, // // 模拟输入
GPIO_Mode_IN_FLOATING = 0x04, // 浮空输入
GPIO_Mode_IPD = 0x28, // 下拉输入
GPIO_Mode_IPU = 0x48, // 上拉输入
GPIO_Mode_Out_OD = 0x14, // 开漏输出
GPIO_Mode_Out_PP = 0x10, // 推挽输出
GPIO_Mode_AF_OD = 0x1C, // 复用开漏输出
GPIO_Mode_AF_PP = 0x18 // 复用推挽输出
}GPIOMode_TypeDef;
3. 配置外部中断线映射
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
将 PB14 引脚映射到外部中断线
GPIO_EXTILineConfig: 函数用于配置外部中断线的映射关系,将 GPIO 引脚与外部中断线相连。
4. 配置外部中断线
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line14; // 指定要配置的外部中断线,如果有多个可以使用 逻辑或(|)
EXTI_InitStruct.EXTI_LineCmd = ENABLE; // 使能
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 工作模式 中断模式 事件模式
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; // 触发方式 上升沿 下降沿 上升/下降沿
EXTI_Init(&EXTI_InitStruct); // 初始化
5. 配置 NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 中断优先级分组
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn; // 指定要配置的中断通道
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; // 使能
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; // 指定中断通道的抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; // 指定中断通道的子优先级
NVIC_Init(&NVIC_InitStruct);
6. 中断处理
void EXTI15_10_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line14) == SET)
{
CountSensor_Count ++;
EXTI_ClearITPendingBit(EXTI_Line14); // 清除中断标志位
}
}
附图: