中断和事件
什么是中断?
中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的 程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。
什么是EXTI?
外部中断/事件控制器(EXTI)管理了控制器的 23 个中断/事件线。每个中断/事件线都对应有一 个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。 EXTI 可以实现对每个中断/事 件线进行单独配置,可以单独配置为中断或者事件,以及触发事件的属性。
其中EXTI的结构体:
- EXTI_Line 就是中断/事件线,共23条
- EXTIMode_TypeDef EXTI_Mode 就是EXTI模式,中断是软件产生的,事件是硬件产生的
- EXTITrigger_TypeDef EXTI_Trigger 就是触发的类型
- FunctionalState EXTI_LineCmd 就是EXTI的控制
一般“ENABLE”即可
什么是优先级?
抢占优先级和响应优先级的区别:
高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。
抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。
抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。
(也就是说,响应优先级再高也不能打断原有的中断,但是当抢占优先级相同时,响应优先级的高低可以决定中断执行的顺序)
如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行(按程序顺序执行)
什么是优先级分组?
Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把 指定中断优先级的寄存器位减少到4位,这4个寄存器位的分组方式如下:
第一种分组 第0组:所有4位用于指定响应优先级
第二种分组 第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级
第三种分组 第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级
第四种分组 第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级
第五种分组 第4组:所有4位用于指定抢占式优先级
什么是NVIC?
STM32通过中断控制器NVIC(Nested Vectored Interrupt Controller)进行中断的管理 。 NVIC是属于Cortex内核的器件,不可屏蔽中断(NMI)和外部中断都由它来处理,但是SYSTICK 不是由NVIC控制的
NVIC的结构体:
1. NVIC_IRQChannel 就是选择中断中断/事件线,共23条
2/3. 分别配置抢占优先级和响应优先级
4. FunctionalState NVIC_IRQChannelCmd 就是NVIC的控制(ENABLE 代表 打开)
什么是中断向量表?
每个中断源,都有对应的处理程序,这个处理程序称为中断服务程序,其入口地址称为中断向量。所有中断的中断服务程序入口地址构成一个表,称为中断向量表;也有的机器把中断服务程 序入口的跳转指令构成一张表,称为中断向量跳转表。
使用中断的方式点亮LED
之前使用的是轮询的方式,即不断WHILE(1)中查询按钮是否被按下,这样实现虽然看起来没什么问题,但是其实,实际还是会有一些小小的时间延迟,比如我按下按钮2,系统还是会先检测是否按下按钮1,如果代码一多,时间的滞后就会更加明显,所以使用中断的方式是一种更好的解决方法。
一、
1.在Keil5进行main函数的编写:
打开gpio.c 可以看到对于刚刚四个GPIO口的设置:
.2 打开stm32f1xx_it.c 可以看到各种中断相关的函数(Handler),拉到最低,可以看到EXTI0和EXTI1的中断相关函数:
两个中断处理函数都跳转到了一个函数,不同的就是输入的参数,右键跳转这个HAL_GPIO_EXTI_IRQHandler():(跳转前先编译,否则识别不到)
这个函数又在调用这个HAL_GPIO_EXTI_Callback的函数,而这个函数的定义也就在下面,并附上了前缀“__weak”,这个意思是这个函数可以被重写,其实这就是中断处理函数,只需要在main函数中,重写这个函数达到想要的目的就可以:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)//中断服务函数
{
switch(GPIO_Pin)
{
HAL_Delay(50);//在检测到按键被按下的低电平的时候,先延迟50ms,再进行判断
case GPIO_PIN_0://如果A0对应的按钮按下
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET)//如果延迟过后依然是低电平
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);//反转LED1的状态
break;
case GPIO_PIN_1:
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET)//如果延迟过后依然是低电平
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);//反转LED2的状态
break;
}
}
2.4 编译并烧录