中断系统
- 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得单片机暂停当前正在运行的的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行。
- 中断优先级:当有多个中断源同时申请中断时,单片机会根据中断源的优先级进行相应(一个工程只能有一个优先级函数)。
- 中断嵌套:当一个中断程序正在运行时,又有新的更高优先级的中断源申请中断,单片机再次暂停当前中断程序,转而去处理新的中断程序,处理完成后依次返回。
中断代码
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 header
int16_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_H
void Encoder_Init(void);
int16_t Encoder_Get(void);
#endif
什么时候使用EXTI
以STM32为例,想要获取的信号时外部驱动的,很快的突发信号需要使用EXTI外部中断。如旋转编码器的输出信号,红外遥控接收头的输出等。