1、stm32f103外部中断控制器EXTI。
1.1外部中断的映像
外部中断只有0~18共19个,那如何给每一个GPIO口配置上中断,通过一个映像把所有具有相同下标的GPIO口映像成相应下标的外部中断。
参考手册:
1.2 外部中断/事件的框图
中断大致过程如下:
- 通过配置 上升沿/下降沿触发选择寄存器 选择 边沿检测电路 所要检测的边沿跳变。
- 边沿检测电路 根据 输入线 是否有相应的边沿跳变,检测到则输出信号1,否则输出信号0。
- 通过一个 或门,或门 以 边沿检测电路、软件中断事件寄存器(中断事件可以通过软件产生) 作为输入。两者之一有一个产生信号1,或门就输出信号1。
- 或门输出的信号1。输出的信号1发至 请求挂起寄存器 。
- 请求挂起寄存器对应寄存器的位置1,然后请求挂起寄存器会产生一个信号1。(不懂,这里暂略)
- 请求挂起寄存器、中断屏蔽寄存器同时输出信号1,则发生信号1到NVIC中断控制器。(注意:这里可以看出中断屏蔽也就是一个与操作。)
事件大致过程如下:
- 通过配置 上升沿/下降沿触发选择寄存器 选择 边沿检测电路 所要检测的边沿跳变。
- 边沿检测电路 根据 输入线 是否有相应的边沿跳变,检测到则输出信号1,否则输出信号0。
- 通过一个 或门,或门 以 边沿检测电路、软件中断事件寄存器(中断事件可以通过软件产生) 作为输入。两者之一有一个产生信号1,或门就输出信号1。
- 或门输出的信号1。若事件屏蔽寄存器也产生信号1,则产生一个信号1发至脉冲发生器,脉冲发生器产生脉冲。
1.3 外部中断的编程。
外部中断配置思路
思路:
- 时钟配置(GPIO时钟、AFIO时钟)
- GPIO配置(中断功能,映射)
- EXTI配置(触发方式,中断使能,)
- NVIC配置(优先级分组,中断使能)
- 中断服务子程序(判断标志,清除标志)
相关寄存器
相关库函数
- GPIO映射函数:
- 外部中断复位配置函数
- 外部中断初始化配置函数
- NVIC
- 清除挂起位标志函数
1.4 按键中断实例。
电路图
代码:
exit_init()
{
GPIO_InitTypeDef gpiost;
EXTI_InitTypeDef extist;
NVIC_InitTypeDef NVIC_InitStructure;
//时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
//GPIO
gpiost.GPIO_Mode=GPIO_Mode_IPU;
gpiost.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4;
gpiost.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&gpiost);//配置PE3,PE4位上拉输出
gpiost.GPIO_Mode=GPIO_Mode_IPD;
gpiost.GPIO_Pin=GPIO_Pin_0;
gpiost.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&gpiost);。。配置PA0为下拉输出
//GPIO映射到EXTI,
//注意:这个函数写参数不能用与运算偷懒,如:GPIO_PinSource3|GPIO_PinSource4,这么写会映射不了,这里搞了半天才发现这里有bug
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);
//EXTI
EXTI_DeInit();
extist.EXTI_Line=EXTI_Line3|EXTI_Line4;
extist.EXTI_LineCmd=ENABLE;
extist.EXTI_Mode=EXTI_Mode_Interrupt;
extist.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_Init(&extist);//外部中断3、外部中断4 下降沿触发
extist.EXTI_Line = EXTI_Line0;
extist.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Init(&extist);//外部中断0 上降沿触发
//NVIC
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; //使能按键KEY1所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //主优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //从优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn; //使能按键KEY0所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}
//外部中断3服务程序
void EXTI3_IRQHandler(void)
{
//做些什么,如:led1=0;
EXTI_ClearITPendingBit(EXTI_Line3); //清除LINE3上的中断标志位
}
//外部中断4服务程序
void EXTI4_IRQHandler(void)
{
//做些什么,如:led2=0;
EXTI_ClearITPendingBit(EXTI_Line4); //清除LINE4上的中断标志位
}
//外部中断0服务程序
void EXTI0_IRQHandler(void)
{
//做些什么,如:led1=1;led2=1;
EXTI_ClearITPendingBit(EXTI_Line0);//清除LINE0上的中断标志位
}
来源:CSDN
作者:某风吾起
链接:https://blog.csdn.net/weixin_43871650/article/details/104407791