中断原理介绍
中断基础知识
1.NVIC中断系统
CortexR-M4集成了嵌套式矢量型中断控制器(Nested Vectored Interrupt Controller (NVIC))来实现高效的异常和中断处理。NVIC实现了低延迟的异常和中断处理,以及电源管理控制
NVIC:中断系统
REXIT:外部中断
中断系统包括外部中断,另外还有定时器中断,串口中断和DMA中断等
2.EXTI外部中断
EXTI(中断/事件控制器)包括23个相互独立的边沿检测电路并且能够向处理器内核产生中断请求或唤醒事件。EXTI有三种触发类型:上升沿触发、下降沿触发和任意沿触发。EXTI中的每一个边沿检测电路都可以独立配置和屏蔽每一个中断都有4位中断优先级配置位,可提供16个中断优先等级。
屏幕剪辑的捕获时间: 2023/5/14 9:59
3.中断触发源
EXTI触发源包括来自I/O管脚的16根线以及来自内部模块的7根线。(包括LVD、RTC闹钟、USB唤醒、以太网唤醒、RTC侵入和时间戳、RTC唤醒)。
通过配置SYSCFG EXTISSx寄存器,所有的GPIO管脚都可以被选作EXTI的触发源。
PA0、PB0、PC0...等引脚不能同时触发中断。
EXTI线编号 0 则触发源的话PA0/PB0/…../PI0
1 则触发源PA1/…/PI1
……15 PA15/PB15/…./PI15
4.中断事件
除了中断,EXTI还可以向处理器提供事件信号,芯片内部有一个唤醒中断控制(WIC),用户可以让处理器和NVIC进入功耗极低的省电模式,有WIC来识别中断和事件以及判断优先级。当某些预期的事件发生时。例如一个特定的IO管脚电平翻转或者RTC脑子动作,EXTI能唤醒处理器及整个系统
5.中断优先级
每一个中断都有4位可配置的优先级位,可以通过分组设置优先级或者响应优先级位数
中断优先级分组或者设置一次,它针对的时系统中所有的中断。后续设置某个中断优先级时,只需要设置在这个分组内的抢占优先级和响应优先级
所有可编程的中断都需要指定抢占优先级和响应优先级,抢占优先级决定是否产生中断嵌套,响应优先级决定中断优先级响应的顺序,若两种优先级一样则看中断在中断向量表中的位置,位置越靠前越先响应
屏幕剪辑的捕获时间: 2023/5/14 10:22
抢占的话就是我先到我就先执行就算你比我高也要等我做完。
响应优先级的话在执行的过程中,抢占到了则先执行抢占
中断操做流程
任意引脚都可以配置触发中断源,使能KEY UP引脚触发中断来检测按键按下
配置触发类型为上升沿触发,KEY UP引脚默认为低电平,按下之后为高电平,产生一个从低到高的过程。所以时上升沿
KEY UP是PA0引脚,需要去选择配置为EXTI0中断线。
外部中断按键点灯
1.配置外部中断
开启时钟
开启GPIO时钟和系统配置时钟
系统配置寄存器可以将外部中断线连接到外面 外面需要的的引脚上
#define BSP_KEY_RCU RCU_GPIOA
开启时钟
Rcu_periph_clock_enable(BSP_KEY_RCU)
Rcu_periph_clock_enable(RCU_SYSCFG);//系统配置时钟
配置GPIO
配置外部中断
1.对NVIC进行分组
Void nvic_priority_group_set(uint32_t nvic_prigroup);
Nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
//设置中断优先级2位用于抢占优先级,2位用于响应优先级
2.设置中断优先级
Void nvic_irq_enable(uint8_t nic_irq,uint8_t nvic_irq_pre_priority,uint8_t nvic_irq_sub_priority);
#define BSP_KEY_EXTI_IRQn EXTI0_IRQn //中断类型
//使能NVIC中断 中断分组为2位抢占优先级2位子优先级
Nvic_irq_enable(BSP_KEY_EXTI_IRQN,3U,3U);
//抢占优先级3,子优先级3
在配置中断优先级之后需要将中断线和GPIO进行连接
Void syscfg_exti_line_config(uint8_t exti_port,uint8_t exti_pin);
#define BSP_KEY_EXTI_PORT_SOURCE EXTI_SOURCE_GPIOA
#define BSP_KEY_EXTI_PIN_SOURCE EXTI_SOURCE_PIN0
//连接中断线到GPIO
Syscfg_exti_line_config(BSP_KEY_EXTI_PORT_SOURCE,BSP_KEY_EXTI_PIN_SOURCE);
配置中断触发类型
void exti init(exti line enum linex, exti mode enum mode, exti trig type enum trig type);
#define BSP KEY EXTI LINE EXTI 0 // 中断线
*初始化中断线*/
exti init(BSP KEY EXTI LINE,EXTI INTERRUPTEXTI TRIG BOTH):
//使能中断
Void exti_interrupt_enable(exti_line_enum linex)
/使能中断*/
Exti_interrupt_enable(BSP_KEY_EXTI_LINE);
2.清中断标志位
Void exti_interrupt_flag_clear(exti_line_enum linex)
/*清楚中断标志位*/
Exti_interrupt_flag_clear(BSP_KEY_EXTI_LINE);
2.中断服务函数
使能中断之后,如果有中断触发,就会跳转到中断服务函数里面去执行。中断函数名是固定的,在startup gd32f450.470.s启动文件中有定义
屏幕剪辑的捕获时间: 2023/5/14 16:15
//配置中断优先级
nvic_irq_enable(BSP_KEY_EXTI_IRQn,3U,3U);
syscfg_exti_line_config(BSP_KEY_EXTI_PORT_SOURCE,BSP_KEY_EXTI_PIN_SOURCE);//配置GPIO PIN为中断(NVIC)线 EXTI0与 PA0相连
//中断初始化 选择中断0 中断事件 上升与下降沿触发(因为这个判断按下或者松开 所以上升与下降都选)
exti_init(BSP_KEY_EXTI_LINE,EXTI_INTERRUPT,EXTI_TRIG_BOTH);
/*中断使能(打开中断)*/
exti_interrupt_enable(BSP_KEY_EXTI_LINE);
//清除中断标志位
exti_interrupt_flag_clear(BSP_KEY_EXTI_LINE);
}
void BSP_KEY_EXTI_IRQHANDLER(void)
{ //获取中断标志位
if (exti_interrupt_flag_get(BSP_KEY_EXTI_LINE) == SET)
{ //按键获取引脚电平状态
if(gpio_input_bit_get(BSP_KEY_PORT,BSP_KEY_PIN)==SET) //这个表明是已经按下
{
/*按键按下操做功能**/
gpio_bit_toggle(PORT_LED1,PIN_LED1);//这里是调用灯的引脚和参数
printf("key press!\r\n");
}else
{
/*按键松开操做功能**/
printf("key release!\r\n");
}
//清除中断标志位
exti_interrupt_flag_clear(BSP_KEY_EXTI_LINE);
}
}
3.实验效果