外部中断
先上两个图
个人理解,如有错误,请谅解
实例以江科大的光电计数传感器为例,讲一下硬件项目来理解外部中断
硬件需求:
C8T6核心板一块,面包板一块,4P的OLED一块,光电计数传感器一个(4P),公对母杜邦线若干,Stlink下载仿真器一个
传感器接线:VCC接面包板正极,GND接面包板负极,DO接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初始化
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配置
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //选择配置NVIC的EXTI15_10线
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC线路使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //指定NVIC线路的抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //指定NVIC线路的响应优先级为1
NVIC_Init(&NVIC_InitStructure);
//计数
uint16_t CountSensor_Get(void)
{
return CountSensor_Count;
}
//中断处理
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line14) == SET) //判断是否是外部中断14号线触发的中断
{
/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
{
CountSensor_Count ++; //计数值自增一次
}
EXTI_ClearITPendingBit(EXTI_Line14); //清除外部中断14号线的中断标志位
//中断标志位必须清除
//否则中断将连续不断地触发,导致主程序卡死
}
}
}
同时贴图配一下文字讲解,图片来源于江协科技PPT
P3
P4
代码块讲解
在使用外部中断时,一般使用步骤,以光电计数传感器为例:
RCC开启外设时钟;
GPIO外设初始化;
AFIO复用配置中断引脚;
EXTI初始化;
NVIC配置;
RCC开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO与AFIO均来自APB2总线;
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);
使用PB14号引脚,因为是光电传感器外部输入中断,所以GPIO_Mode设置为XX输入;这里是IPU上拉输入,可以确保在需要输入信号但没有外部驱动时,输入端口会被上拉到逻辑高电平(通常是 Vcc)。这在需要读取外部开关、按键等设备状态时非常有用,因为它可以防止输入端口浮动并引起不确定的逻辑状态。
AFIO复用配置中断引脚
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
GPIO_EXTILineConfig 函数的主要作用是将指定的 GPIO 引脚配置为外部中断线路。这意味着当外部事件(例如引脚状态变化)发生时,可以触发相应的中断处理程序。在此处,是将PB14引脚配置为外部中断线路,参考上面P3图的流程示意图;
EXTI初始化
EXTI_InitTypeDef EXTI_InitStructure;
//EXTI_Line14将外部中断线路选择为 EXTI Line 14,表示我们要使用 GPIOB 的第 14 号引脚作为触发源
EXTI_InitStructure.EXTI_Line = EXTI_Line14;
//使能,启用14号
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
//将外部中断线路 EXTI_Line14 配置为中断模式。这意味着当与 EXTI_Line14 关联的 GPIO 引脚产生了上升沿信号时,系统将会立即执行与之相关联的中断服务程序来处理这一时间。
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
//表示将外部中断配置为下降沿触发方式。在下降沿触发方式下,当外部中断引脚从高电平变为低电平时,系统会响应并执行与该中断相关的处理程序。
//这里说明下,Trigger是触发模式,三种触发,
//上升沿触发-EXTI_Trigger_Rising = 0x08;
//下降沿触发-EXTI_Trigger_Falling = 0x0C, ;
//上升下降沿触发EXTI_Trigger_Rising_Falling = 0x10
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure);
现在P3的流程结束,来到P4的NVIC
NVIC配置
//这行代码用于配置 NVIC 的中断优先级分组方式为分组2。在 Cortex-M 处理器中,中断优先级分为抢占优先级和子优先级两部分,分组2表示抢占优先级占4位,子优先级占0位.
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //选择配置NVIC的EXTI15_10线
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC线路使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //指定NVIC线路的抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //指定NVIC线路的响应优先级为1
NVIC_Init(&NVIC_InitStructure);
还有点明天填坑