概述
STM32的每个IO都可以作为外部中断输入。
STM32的中断控制器支持19个外部中断/事件请求:
线0~15:对应外部IO口的输入中断。
线16:连接到PVD输出。
线17:连接到RTC闹钟事件。
线18:连接到USB唤醒事件。
每个外部中断线可以独立的配置触发方式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专用的状态位。
从上面可以看出,STM32供IO使用的中断线只有16个,但是STM32F10x系列的IO口多达上百个,STM32F103ZET6(112),
映射关系
STM32F103RCT6(51),那么中断线怎么跟 I/O 口对应呢?
采用的是映射关系,
GPIOx.0映射到EXTI0
GPIOx.1映射到EXTI1
…
GPIOx.15映射到EXTI15
即每一组I/O口的一个固定I/O映射到对应的线上。每组I/O为0~15共16个,恰好与外部中断线的数目一致。
对于每个中断线,我们可以设置相应的触发方式(上升沿触发(EXTI_Trigger_Rising),下降沿触发(EXTI_Trigger_Falling),边沿触发(EXTI_Trigger_Rising_Falling))以及使能。
正文
在51单片机里面每一个中断都对应有一个中断服务函数,但是在stm32里面就不是,外部中断一共只有七个中断服务函数,中断0~4每一个外部中断对应一个中断服务函数,中断5~9对应一个(即中断5~中断9进入的是同一个中断服务函数),中断10~15对应一个。一共七个。
中断服务函数列表:
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler
外部中断的一般配置步骤:
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();
注意:既然用到了NVIC就需要先分组:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置分组为 2
几个函数解释:
1,初始化线上中断: `void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct) // 位于stm32f10x_exti.c 文件中`
该函数的参数为一个结构体指针
typedef struct
{
uint32_t EXTI_Line; // 中断线
EXTIMode_TypeDef EXTI_Mode; // 方式 :中断 或者 事件
EXTITrigger_TypeDef EXTI_Trigger; // 中断触发方式(下降沿,上升沿,或者 双边沿) 前面有对应的值
FunctionalState EXTI_LineCmd; // 中断使能(ENABLE or DISABLE)
}EXTI_InitTypeDef;
2,void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)// 位于 misc.c 中
该参数同样是一个结构体指针
typedef struct
{
uint8_t NVIC_IRQChannel; // 外部中断几, 取值:EXTI0_IRQn、EXTI1_IRQn、EXTI2_IRQn、EXTI3_IRQn、EXTI9_5_IRQn
// 这个参数的取值位于:stm32f10x.h 的 186 行,以及后面
uint8_t NVIC_IRQChannelPreemptionPriority; // 抢占优先级等级,范围与分组有关
uint8_t NVIC_IRQChannelSubPriority; // 响应优先级等级,范围与分组有关
FunctionalState NVIC_IRQChannelCmd; // 使能, 取值(ENABLE 或者 DISABLE)
} NVIC_InitTypeDef;
3,标志位清零函数:void EXTI_ClearITPendingBit(uint32_t EXTI_Line)// 位于stm32f10x_exti.c 文件中
这个函数是用来清楚中断标志位的,如果某个中断产生,硬件会自动将该中断对应的标志位置 1 ,需要手动清零, 一般放在中断里面。