STM32学习笔记(1)中断
本文章适用于STM32F103RBT6,其他型号可能有所不同
开发模板见我的GitHub仓库skyone-wzw@STM32F103RBT6-template
如果你觉得这篇文章有帮助,请star仓库或评论回复吧~
如果文章有任何错误(包括错别字)可以在这里提交Issue或邮件联系我
设置NVIC中断分组
用到的函数
NVIC_PriorityGroupConfig()
设置中断分组
可选:
-
NVIC_PriorityGroup_0
抢占优先级0位,响应优先级4位
-
NVIC_PriorityGroup_1
抢占优先级1位,响应优先级3位
-
NVIC_PriorityGroup_2
抢占优先级2位,响应优先级2位
-
NVIC_PriorityGroup_3
抢占优先级3位,响应优先级1位
-
NVIC_PriorityGroup_4
抢占优先级4位,响应优先级0位
抢占优先级与响应优先级
这两个优先级都是数值越小,优先级越高
- 当A中断抢占优先级高于B中断,不论响应优先级如何,如果中断同时发生,A中断先执行,B中断后执行;如果B中断正在执行,A中断发生,A中断可以打断B中断的执行,先执行A中断,再继续执行B中断。
- 当A中断抢占优先级与B中断相等,如果A中断响应优先级高于B中断,如果中断同时发生,A中断先执行,B中断后执行;如果B中断正在执行,A中断发生,A中断不可以打断B中断的执行!
中断线和中断初始化
相关函数
GPIO_EXTILineConfig(GPIO_PortSource, GPIO_PinSource)
IO口与中断线连接
例如:
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
// GPIOA_1 与中断线1连接
EXTI_Init(&EXTI_InitTypeDef)
定义中断类型,即当什么时候触发中断
对于结构体EXTI_InitTypeDef
typedef struct {
// 中断线:0~15
uint32_t EXTI_Line;
/* 选择模式:
* 产生中断(EXTI_Mode_Interrupt)
* 产生事件(EXTI_Mode_Event)
*/
EXTIMode_TypeDef EXTI_Mode;
/* 选择触发方式:
下降沿触发(EXTI_Trigger_Falling)
上升沿触发(EXTI_Trigger_Rising)
上升沿和下降沿都触发(EXTI_Trigger_Rising_Falling)
*/
EXTITrigger_TypeDef EXTI_Trigger;
// 使能中断线
FunctionalState EXTI_LineCmd;
} EXTI_InitTypeDef;
例如:
EXTI_InitTypeDef exti;
// 选择要设置的中断线
exti.EXTI_Line = EXTI_Line3;
// 选择模式:产生中断
exti.EXTI_Mode = EXTI_Mode_Interrupt;
// 选择触发方式为下降沿触发
exti.EXTI_Trigger = EXTI_Trigger_Falling;
// 使能
exit.EXTI_LineCmd = ENABLE;
EXTI_Init(&exti);
中断线
中断线有16个:0~15
每组GPIOx
都有16个IO,GPIOA_0
、GPIOB_0
等分别对应中断线0,以此类推。
设置中断优先级
相关函数
NVIC_Init(&NVIC_InitTypeDef)
设置中断优先级
对应结构体NVIC_InitTypeDef
typedef struct {
// 设置中断通道
uint8_t NVIC_IRQChannel;
// 设置抢占优先级
uint8_t NVIC_IRQChannelPreemptionPriority;
// 设置响应优先级
uint8_t NVIC_IRQChannelSubPriority;
// 使能
FunctionalState NVIC_IRQChannelCmd;
} NVIC_InitTypeDef;
例如:
NVIC_InitTypeDef nvic;
// 设置中断通道为:第0通道
nvic.NVIC_IRQChannel = EXTI0_IRQn;
// 设置抢占优先级为:2
nvic.NVIC_IRQChannelPreemptionPriority = 0x02;
// 设置响应优先级为:3
nvic.NVIC_IRQChannelSubPriority = 0x03;
// 使能
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
中断通道
中断通道一共7个:
EXTI0_IRQn
EXTI1_IRQn
EXTI2_IRQn
EXTI3_IRQn
EXTI4_IRQn
EXTI9_5_IRQn
EXTI15_10_IRQn
中断处理函数
中断处理函数与中断通道一一对应一共7个
void EXTI0_IRQHandler()
void EXTI1_IRQHandler()
void EXTI2_IRQHandler()
void EXTI3_IRQHandler()
void EXTI4_IRQHandler()
void EXTI9_5_IRQHandler()
void EXTI15_10_IRQHandler()
常用API:
-
ITStatus EXTI_GetITStatus(EXTI_Line)
判断指定中断线上,是否发生中断,常用于
EXTI9_5
与EXTI15_10
上判断具体是哪一个中断线上来的中断 -
void EXTI_ClearITPendingBit(EXTI_Line)
消除指定中断线上的中断标志,中断处理操作完成后必须调用!
中断、中断线、中断通道、中断处理函数的关系
以西瓜汁生产线类比:
GPIO引脚触发中断相当于果园生产西瓜
中断线相当于西瓜运输线
中断通道相当于运输线上的桥,例如运输线1(中断线1)必须经过桥1(中断通道1),运输线5-9(中断线5到中断线9)必须经过桥9_5(EXTI9_5_IRQn
)
中断处理函数相当于西瓜汁生产厂,处理运来的西瓜
所有流程
该流程不包括GPIO的配置
-
设置中断分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
-
初始化中断线
// 连接中断线3
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource3);
EXTI_InitTypeDef exti;
// 中断线3、产生中断、下降沿触发 使能
exti.EXTI_Line = EXTI_Line3;
exti.EXTI_Mode = EXTI_Mode_Interrupt;
exti.EXTI_Trigger = EXTI_Trigger_Falling;
exti.EXTI_LineCmd = EANBLE;
EXTI_Init(&exti); -
设置中断优先级
NVIC_InitTypeDef nvic;
// 中断通道3(对应中断线3) 抢占优先级2 响应优先级3 使能
NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); -
定义中断处理函数
void EXTI0_IRQHandler(void) {
delay_ms(10); // 消抖
if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3)) {
if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1)) {
GPIO_ResetBits(GPIOA, GPIO_Pin_1);
} else {
GPIO_SetBits(GPIOA, GPIO_Pin_1);
}
}
EXTI_ClearITPendingBit(EXTI_Line3);
}