在讲三轴加速度计的时候,提到外部中断。接下来就看看中断为什么这么配置。
一、外部中断概述
STM32的每个IO都可以作为外部中断输入。
那我们之前讲过的,参看:STM32开发 – GPIO详解
STM32F105RC 一共有4组IO口 一共16X3+3=51个IO
GPIOA0~A15
GPIOB0~B15
GPIOC0~C15
GPIOD0~D2
那么它跟中断的关系是什么呢?
STM32的中断控制器支持19个外部中断/事件请求:
从图上来看,GPIO 的管脚 GPIOx.0~GPIOx.15(x=A,B,C,D,E,F,G)分别对应中断线 0 ~ 15。
另外四个EXTI线的连接方式如下:
● EXTI线16连接到PVD输出
● EXTI线17连接到RTC闹钟事件
● EXTI线18连接到USB唤醒事件
● EXTI线19连接到以太网唤醒事件(只适用于互联型产品)
对于每个中断线,我们可以设置相应的触发方式(上升沿触发,下降沿触发,边沿触发)以及使能。
二、设置中断相应的触发方式以及使能
void BSP_LIS3DH_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource8); //配置GPIO与中断线的映射关系
/*中断的初始化*/
EXTI_InitStructure.EXTI_Line=EXTI_Line8;
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); //初始化外设EXTI寄存器
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //使能按键外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; //抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x07; //响应优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //中断优先级分组初始化
}
void EXTI9_5_IRQHandler (void)
{
if(EXTI_GetITStatus(EXTI_Line8)!=RESET)
{
LIS3DH_Rx_Len = LIS3DH_Fifo_Read(LIS3DHBuffer);
EXTI_ClearITPendingBit(EXTI_Line8);
}
}
程序上是这么配置的,但是这些都是什么意思呢?接下来看一下咯!!
1、中断服务函数列表:
IO口外部中断在中断向量表中只分配了7个中断向量,也就是只能使用7个中断服务函数。
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler
外部中断线5~9分配一个中断向量,共用一个服务函数。
外部中断线10~15分配一个中断向量,共用一个中断服务函数。
注意,是共用中断入口,实际操作需要在中断里面判断是哪一个中断。
如下代码:if(EXTI_GetITStatus(EXTI_Line8)!=RESET)
在EXTI9_5_IRQHandler 中断里,判断是否是EXTI_Line8的中断。
void EXTI9_5_IRQHandler (void)
{
if(EXTI_GetITStatus(EXTI_Line8)!=RESET)
{
LIS3DH_Rx_Len = LIS3DH_Fifo_Read(LIS3DHBuffer);
EXTI_ClearITPendingBit(EXTI_Line8);
}
}
2、外部中断常用库函数
①void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
设置IO口与中断线的映射关系
例如, GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2);
②void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
初始化中断线:触发方式等
③ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
判断中断线中断状态,是否发生
④void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
清除中断线上的中断标志位
3、EXTI_Init函数介绍
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line=EXTI_Line8; //指定要配置的中断线
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //模式:事件 或 中断
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //触发方式:上升沿/下降沿/双沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能 或 失能
EXTI_Init(&EXTI_InitStructure); //初始化外设EXTI寄存器
上面的例子设置中断线 8 上的中断为下降沿触发
4、设置 NVIC 中断优先级
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; //使能按键外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; //抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x07; //响应优先级2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //中断优先级分组初始化
5、中断服务函数
void EXTI9_5_IRQHandler (void)
{
if(EXTI_GetITStatus(EXTI_Line8)!=RESET)
{
LIS3DH_Rx_Len = LIS3DH_Fifo_Read(LIS3DHBuffer);
EXTI_ClearITPendingBit(EXTI_Line8);
}
}
三、外部中断的一般配置步骤
1、初始化IO口为输入。
GPIO_Init();
2、开启IO口复用时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
3、设置IO口与中断线的映射关系。
void GPIO_EXTILineConfig();
4、初始化线上中断,设置触发条件等。
EXTI_Init();
5、配置中断分组(NVIC),并使能中断。
NVIC_Init();
6、编写中断服务函数。
EXTIx_IRQHandler();
7、清除中断标志位
EXTI_ClearITPendingBit();
上一篇:STM32开发 -- UTC、UNIX时间戳、北京时间之间的转换
下一篇:STM32开发 -- IAP详解
推荐阅读最新更新时间:2024-11-11 18:20