外部中断配置过程5步骤
1.配置RCC,开启外设时钟(EXTI和NVIC不需要我们自己开启时钟) 2.配置GPIO 3.配置AFIO外部中断引脚(相同的pin不能同时触发引脚如PA0和PB0) 4.配置EXTI,选择边沿触发方式,如下降沿等,选择中断响应或者事件响应。 5.配置NVIC,选择合适优先级 最后配置外部中断函数
????????中断就是暂停手头运行程序,转而执行按照优先级顺序的中断源程序。
? ? ? ? ?由于stm32有68个可屏蔽中断通道(包含EXTI、TIM、ADC、USART、SPI、I2C、RTC等多个外设),所以需要NVIC(嵌套中断向量)统一管理。每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级。(就好比医院有68个门诊窗口,一次只开放门诊16个,每个门诊一次只有1个人看病,而这些人里面可能有紧急病患,和一般病患,那么医院就会给他们优先排序(NVIC管理优先顺序顺序)这就是抢占优先级,和响应优先级)。
?????????NVIC的中断优先级由优先级寄存器的4位(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的响应优先级 抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和响应优先级均相同的按中断号排队。
??????? EXTI(Extern Interrupt)外部中断
????????EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序。
????????EXIT有16个gpio通道,但是每个gpio通道都有16个口,为防止16个通道不够用,所以设置一个AFIO中断引脚选择电路模块。(在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择)
按键计数代码
CountSensor.c
#include "stm32f10x.h" // Device header
uint16_t CountSensor_counter;
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_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);//AFIO中断引脚选择
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_counter;
}
void EXTI15_10_IRQHandler(void) //中断函数
{
if(EXTI_GetITStatus(EXTI_Line14)==SET) //判断是否进入中断
{
CountSensor_counter++;
EXTI_ClearITPendingBit(EXTI_Line14); //清除中断标志位
}
}
main.c
#include "stm32f10x.h" // Device header
#include "CountSensor.h"
#include "Oled.h"
uint16_t num;
int main(void)
{
CountSensor_Init();
OLED_Init();
OLED_ShowString(1,1,"count:");
while (1)
{
num=CountSensor_Get();
OLED_ShowNum(1,7,num,5);
}
}
|