学习笔记:
外部中断简介:
中断分类
STM32的每个IO都可以作为外部中断输入,STM32的中断控制器支持19哥外部中断/事件请求:
0-15 I/O输入中断
16:连接到PVD输出。
17:连接到RTC闹钟事件。
18:连接到USB唤醒事件。
触发方式:
(1)上升沿:EXTI_Initstructure.EXTI_Trigger=EXTI_Trigger_Rising;
(2)下降沿:EXTI_Initstructure.EXTI_Trigger=EXTI_Trigger_Falling;
(3)双边沿触发:EXTI_Initstructure.EXTI_Trigger=EXTI_Trigger_Rising_Falling;
中断线的分配:
因为STM32有上百个I/O,但只有16跟线,所以有一种独特的分配方式:
GPIOX0-----------exti0
.
.
.以此类推
即:
### 中断服务函数的分类:
STM32提供16个中断线,但是只提供7个中断向量,只有7个中断服务函数:
(可在startup_stem32f10x_xx.s文件中找到)
EXTI0| EXTI1| EXTI2 |ECTI3 | EXTI4分别有自己的中断服务函数
EXTI9-5用一个
EXTI15-10用一个
中断服务函数列表:
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler
初始化步骤:
(1)初始化所用的外部中段I/0口
本篇以cet711为例:
选用按键B1,由电路图可得,连接为PA0口
在这里外部跳线帽将NK1和MPA0连接在一起
由图可知,按键按下后,读入低电平。
配置:
使能时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
PA0上拉输入
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_Init(GPIOA,&GPIO_InitStructure);`
(2)配置I/O与中断线连接:(映射关系)
因为所用PA0所以用exti0线映射,
时钟初始化:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
映射:
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
(3)初始化中断线:(触发方式)
EXTI_InitTypeDef EXTI_Initstructure;
EXTI_Initstructure.EXTI_Line=EXTI_Line0;
EXTI_Initstructure.EXTI_LineCmd=ENABLE;
EXTI_Initstructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_Initstructure.EXTI_Trigger=EXTI_Trigger_Falling;//ϽµÑØ´¥·¢
EXTI_Init(&EXTI_Initstructure);
(4)中断优先级管理:
1.中断优先级分组(写在主函数中,exti_init()之前):
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
中断优先级分组可以配置寄存器SCB->AIRCR从而分配寄存器中优先级的位,如2位分配给抢占优先级,2位分配给相应优先级。即抢占优先级分四个0——3,响应优先级分四个0——3
2.中断优先级分配:
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;//中断线0
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&NVIC_InitStructure);
以上初始化结束
(5)写中断服务函数:
void EXTI0_IRQHandler(void)
{
delay_ms(10);//消抖
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0)//判断是否按下
{
LED_LI(1);//灯亮
beep_con(1);//蜂鸣器叫
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
EXTI_ClearITPendingBit(EXTI_Line0);//这句话用来清空中断标志位
外部中断标志位无法自动清空需要手动在中断服务函数中清空。
中断服务函数作用: 当中断发生时,进入中断服务函数中执行,然后在继续执行主程序。
代码
void EXITA_INIT(void)
{
EXTI_InitTypeDef EXTI_Initstructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_Init(GPIOA,&GPIO_InitStructure);
EXTI_Initstructure.EXTI_Line=EXTI_Line0;
EXTI_Initstructure.EXTI_LineCmd=ENABLE;
EXTI_Initstructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_Initstructure.EXTI_Trigger=EXTI_Trigger_Falling;//ϽµÑØ´¥·¢
NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
EXTI_Init(&EXTI_Initstructure);
NVIC_Init(&NVIC_InitStructure);
}
void EXTI0_IRQHandler(void)
{
delay_ms(10);
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0)
{
LED_LI(1);
beep_con(1);
}
EXTI_ClearITPendingBit(EXTI_Line0);
}