中断系统
- 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得单片机暂停当前正在运行的的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行。
- 中断优先级:当有多个中断源同时申请中断时,单片机会根据中断源的优先级进行相应(一个工程只能有一个优先级函数)。
- 中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,单片机再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次返回。
中断代码
int mian(void) //主函数
{while(1){}}
void EXTI0_IRQHandler(void) //中断函数
{}
STM32中断
- STM32中断包含EXTI外部中断,TIM定时中断,ADC数模中断,USART串口中断,SPI通讯中断,IIC通讯中断,RTC实时时钟等多个外设中断。
- 使用NVIC1统一管理中断,每个中断通道都拥有16个可编程的优先等级,可对优先级进行分组,进一步设置抢占优先级和响应优先级。
- NVIC的优先级分组:NVIC的中断优先级由优先级寄存器的4为(0~15)决定,这4位可以进行切分,分为高n位的抢占优先级和低4-n位的相应优先级。抢占优先级高的可以中断嵌套,响应优先级高的可以优先排队,抢占优先级和相应优先级均相同的按中断号排队
分组方式 | 抢占优先级 | 抢占优先级 |
---|---|---|
分组0 | 0位,取值0 | 4位,取值0~15 |
分组1 | 1位,取值0~1 | 4位,取值0~7 |
分组2 | 2位,取值0~3 | 4位,取值0~3 |
分组3 | 3位,取值0~7 | 4位,取值0~1 |
分组4 | 4位,取值0~15 | 4位,取值0 |
EXTI外部中断
- EXTI可以检测GPIO口的电平变化,GPIO口的电频变化时即可申请中断。
- EXTI的支持触发方式:上升沿,下降沿,双边沿,软件触发
- 支持所有的GPIO口但相同的Pin不能同时触发中断
- 通道数:16个GPIO_Pin,PVD输出,RTC闹钟,USB唤醒,以太网唤醒
- 触发响应方式:中断响应/事件响应2
EXTI中断基本结构
EXTI代码
根据EXTI中断的基本结构图可以写出配置中断的函数,这里展示以旋转编码器为例的库函数(这里为双中断)
- .c文件:
#include "stm32f10x.h" // Device headerint16_t Encoder_Count;void Encoder_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_0 | GPIO_Pin_1;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);EXTI_InitTypeDef EXTI_InitStructure;EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;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 = EXTI0_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;NVIC_Init(&NVIC_InitStructure);
}int16_t Encoder_Get(void)
{int16_t Temp;Temp = Encoder_Count;Encoder_Count = 0;return Temp;
}void EXTI0_IRQHandler(void)
{if (EXTI_GetITStatus(EXTI_Line0) == SET){if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0){Encoder_Count --;}EXTI_ClearITPendingBit(EXTI_Line0);}
}void EXTI1_IRQHandler(void)
{if (EXTI_GetITStatus(EXTI_Line1) == SET){if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0){Encoder_Count ++;}EXTI_ClearITPendingBit(EXTI_Line1);}
.h文件(中断函数无需声明):
#ifndef __ENCODER_H
#define __ENCODER_Hvoid Encoder_Init(void);
int16_t Encoder_Get(void);#endif
什么时候使用EXTI
以STM32为例,想要获取的信号时外部驱动的,很快的突发信号需要使用EXTI外部中断。如旋转编码器的输出信号,红外遥控接收头的输出等。
NVIC的基本结构:
NVIC为内核外设,程序中不需要开启专门的NVIC时钟。 ↩︎中断响应:申请中断,让CPU执行中断函数
事件响应:外部中断的信号不通向CPU,转而通向其他外设,触发其他外设的操作,如:ADC转换,DMA等。 ↩︎