1、项目目的
使用中断的方法,按下
KEY1
翻转
LED1
状态,而
LED2
一直保持
500ms
的频率闪烁。
注意:
按键驱动一般使用轮询法。
如果采用中断法,由于软件消抖需要在中断服务函数加入延时函数,这种做法一般是不被允许的。由于还未学到传感器模块及定时器,本实验暂时在中断服务函数中加入延时函数。
2、EXTI配置流程
3、简单阐述EXTI和NVIC的关系
在单片机中,EXTI(外部中断 / 事件控制器)和 NVIC(嵌套向量中断控制器)有着密切的关系。
一、EXTI 的作用
EXTI 主要负责检测外部信号的变化,当外部事件发生时,如按键按下、外部传感器信号变化等,EXTI 可以触发中断请求。它允许配置多个外部中断线,每个中断线可以独立地设置触发方式(上升沿、下降沿、双边沿等)。
二、NVIC 的作用
NVIC 是整个中断系统的核心控制器。它负责管理和分配中断优先级,决定中断的响应顺序。当多个中断同时发生时,NVIC 根据中断优先级来决定先处理哪个中断。NVIC 还支持中断嵌套,高优先级的中断可以打断低优先级的中断处理程序。
三、两者的关系
-
触发关系
- EXTI 检测到外部事件后,会向 NVIC 发送中断请求信号。NVIC 接收到请求后,根据中断优先级和当前系统状态,决定是否响应这个中断。
- 如果 NVIC 允许响应,它会将控制权转移到相应的中断服务程序(ISR),执行中断处理任务。
-
优先级管理
- NVIC 为每个中断源分配了一个优先级。对于由 EXTI 触发的中断,NVIC 可以根据其优先级来决定中断的响应顺序。
- 通过合理设置 EXTI 和 NVIC 的优先级,可以确保关键的外部事件能够及时得到处理,同时避免低优先级的中断影响系统的实时性。
-
中断嵌套支持
- 由于 NVIC 支持中断嵌套,当一个高优先级的外部中断通过 EXTI 触发后,如果此时有低优先级的中断正在处理,高优先级中断可以打断低优先级中断的处理,优先执行。
- 这种中断嵌套机制可以提高系统对紧急外部事件的响应能力。
- 总之,在单片机中,EXTI 和 NVIC 协同工作,共同实现对外部事件的快速响应和中断处理。EXTI 负责检测外部事件并触发中断请求,而 NVIC 则负责管理中断优先级和控制中断的响应顺序,确保系统能够高效、稳定地处理各种外部中断。
4、项目代码
exti.c
#include "exti.h"
#include "sys.h"
#include "delay.h"
#include "led.h"
void exti_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
//打开时钟
__HAL_RCC_GPIOA_CLK_ENABLE(); // 使能GPIOA时钟
//调用GPIO初始化函数
gpio_initstruct.Pin = GPIO_PIN_0; // 按键对应的引脚
gpio_initstruct.Mode = GPIO_MODE_IT_FALLING; // 下降沿触发
gpio_initstruct.Pull = GPIO_PULLUP; // 上拉
HAL_GPIO_Init(GPIOA, &gpio_initstruct);
HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0); // 设置EXTI0中断线的优先级
HAL_NVIC_EnableIRQ(EXTI0_IRQn); // 使能中断
}
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
delay_ms(20);
if (GPIO_Pin == GPIO_PIN_0)
{
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
led1_toggle();
}
}
exti.h
#ifndef __EXTI_H__
#define __EXTI_H__
void exti_init(void);
#endif
main.c
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "exti.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* 初始化LED灯 */
exti_init(); /* 初始化EXTI */
while(1)
{
led2_off();
delay_ms(500);
led2_on();
delay_ms(500);
}
}
led代码上文都有这里不添加了
5、补充一点
修改NVIC_PRIORITYGROUP_2(修改成2就可以了)