????在我们学习STM32时中断是一个必不可少的部分,中断能够帮助我们解决很多问题,下面就让小编给大家展示STM32中断相关知识吧。
一、中断的定义
????中断就是CUP暂时中断正在执行的程序,转而去执行中断请求的外设或者事件的服务程序,待处理完毕中断服务程序后再执行原程序。例如,小明正在看书(CUP的主程序),这时有人打电话给小明,小明就去接这个电话(中断服务函数),接完电话后小明接着去看书(CPU主函数)。
二、中断的作用
1、提高CPU的利用率; 2、具有实时功能; 3、具有故障处理功能; 4、能够实现分时操作;
三、中断处理的过程
第一步,中断响应。这时需要保护现场,并且找到中断对应的中断服务程序的地址,即中断向量表。(一般由硬件自动实现) 第二步,执行中断服务函数。中断服务函数既没有参数,也没有返回值,更不需要用户调用;中断服务函数是中断产生后,才执行的一个函数。(由用户编程) 第三步,中断返回。恢复现场。(由硬件自动实现)
四、STM32F103的中断系统
1、嵌套向量中断控制器NVIC
????向量中断控制器,简称NVIC,访问地址是OxE000_E000,共支持1至240个外部中断输入(通常外部中断写作 IRQs),具体的数值由芯片厂商在设计芯片时决定。此外,NVIC还支持一个“永垂不朽”的不可屏蔽中断(NMI〉输入。所有NVIC的中断控制/状态寄存器都只能在特权级下访问。不过有一个例外——软件触发中断寄存器可以在用户级下访问以产生软件中断。所有的中断控制/状态寄存器均可按字/半字/字节的方式访问。由于NVIC集成在ARM Cortex-M3内核中,与中央处理器核心CM3Core紧密耦合,从而实现低延迟的中断处理和高效地处理晚到的较高优先级的中断。 NVIC中断控制器:
- (1)支持84个异常,包括16个内部异常和68个非内核异常中断;
- (2)使用4位优先级设置,具有16级可编程异常优先级;
- (3)中断响应时处理器状态的自动保存,无须额外指令;
- (4)中断返回时处理器状态的自动恢复,无须额外指令;
- (5)支持嵌套和向量中断;
- (6)支持中断尾链技术。
2、STM32F103中断优先级
- (1)抢占式优先级
????高抢占式优先级的中断事件会打断当前的主程序/中断程序运行,俗称中断嵌套。 - (2) 响应优先级
????在抢占式优先级相同的情况下,高响应优先级的中断优先被响应。 - (3)中断响应依据
????首先,比较抢占式优先级;其次,比较响应优先级。是否含有中断嵌套取决于抢占优先级。 - (4)优先级冲突的处理
????具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断的嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。
STM32F013对优先级的设定
五、函数解析
1、NVIC_DeInit函数
2、NVIC_Init函数
3、NVIC_PriorityGroupConfig函数
4、EXTI_Init函数
5、EXTI_DeInit函数
6、EXTI_GetITStatus函数
7、EXTI_ClearFlag函数
8、GPIO引脚中断映射函数
六、示例功能
????在STM32F103ZET6开发板上,有五个按键与八个LED灯,现在我们需要按下KEY1点亮LED1、按下KEY2点亮LED2……按下KEY5点亮LED5。
1、中断初始化函数
????在中断初始化函数中,我们需要注意的是GPIO引脚与中断的映射关系。GPIO引脚、外部线路EXTI_Line的值、指定中断通道NVIC_IRQChannel的值都需要一样,不然定义中断就没有效果。例如我们需要使用外部中断6,那么我们就需要选择GPIO_Pin6、EXTI_Line6与EXTI9_5_IRQn。(外部中断的Pin5-Pin9所用的是同一个中断通道。)
void exit_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO , ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource0);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource1);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource2);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource3);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource6);
EXTI_InitStructure.EXTI_Line = EXTI_Line0|EXTI_Line1|EXTI_Line2|EXTI_Line3|EXTI_Line6;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
2、中断响应函数
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0)==SET)
{
EXTI_ClearFlag(EXTI_Line0);
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_0)==Bit_RESET)
{
exit_flag = 1;
}
}
}
void EXTI1_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line1)==SET)
{
EXTI_ClearFlag(EXTI_Line1);
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_1)==Bit_RESET)
{
exit_flag = 2;
}
}
}
void EXTI2_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line2)==SET)
{
EXTI_ClearFlag(EXTI_Line2);
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==Bit_RESET)
{
exit_flag = 3;
}
}
}
void EXTI3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3)==SET)
{
EXTI_ClearFlag(EXTI_Line3);
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==Bit_RESET)
{
exit_flag = 4;
}
}
}
void EXTI9_5_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line6)==SET)
{
EXTI_ClearFlag(EXTI_Line6);
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_6)==Bit_RESET)
{
exit_flag = 5;
}
}
}
3、中断服务函数
extern unsigned char exit_flag;
void exti_pro(void)
{
LED_all_off();
if(exit_flag == 1){
LED_ctrl(LED1,LED_ON);
}else if(exit_flag == 2){
LED_ctrl(LED2,LED_ON);
}else if(exit_flag == 3){
LED_ctrl(LED3,LED_ON);
}else if(exit_flag == 4){
LED_ctrl(LED4,LED_ON);
}else if(exit_flag == 5){
LED_ctrl(LED5,LED_ON);
}else{
LED_all_off();
}
}
4、主函数
int main(void)
{
LED_GPIO_init();
key_GPIO_init();
exit_Init();
while(1){
exti_pro();
}
}
七、 附
????假如大家想看相关模块的内容请点击链接前往:STM32-按键、STM32-刷新数码管、STM32-八位流水灯、STM32-配置SysTick定时器
|