中断优先级NVIC
STM32 的中断向量具有两个属性,一个为抢占属性,另一个为响应属性,其属性编号越小,表明它的优先级别越高。
抢占,是指打断其他中断的属性,即因为具有这个属性会出现嵌套中断(在执行中断服务函数A 的过程中被中断B 打断,执行完中断服务函数B 再继续执行中断服务函数A),抢占属性由NVIC_IRQChannelPreemptionPriority 的参数配置。
而响应属性则应用在抢占属性相同的情况下,当两个中断向量的抢占优先级相同时,如果两个中断同时到达, 则先处理响应优先级高的中断, 响应属性由NVIC_IRQChannelSubPriority 参数配置
中断优先级分组
通过寄存器SCB->AIRCR的[10:8]位进行配置
第0组:所有4位用于指定响应优先级
第1组:最高1位用于指定抢占式优先级,最低3位用于指定响应优先级
第2组:最高2位用于指定抢占式优先级,最低2位用于指定响应优先级
第3组:最高3位用于指定抢占式优先级,最低1位用于指定响应优先级
第4组:所有4位用于指定抢占式优先级
外部中断
在STM32F1中,每个IO口都可以作为外部中断的中断输入口,共有19个外部中断
EXTI 线 0~15:对应外部 IO 口的输入中断。
EXTI 线 16:连接到 PVD 输出。
EXTI 线 17:连接到 RTC 闹钟事件。
EXTI 线 18:连接到 USB 唤醒事件。
EXTI 线 19:连接到以太网唤醒事件。
对于IO口的输入中断只有16个,其他的暂时也用不上。但是并不是每个IO口对应一个输入中断,而是多个管脚共用一个外部中断。
Pin0对应EXTI0,Pin1对应EXTI1…
这样一来,16种管脚正好对应16个外部中断。当要进行外部中断输入选择IO口时,一次只能选择一个IO口,所以需要进行选择。
不过要注意的是外部中断的中断服务函数只有7个,所以必然有几种是共用同一个中断服务函数的
void EXTI0_IRQHandler();
void EXTI1_IRQHandler();
void EXTI2_IRQHandler();
void EXTI3_IRQHandler();
void EXTI4_IRQHandler();
void EXTI9_5_IRQHandler();
void EXTI15_10_IRQHandler()
- 使能 IO 口时钟,初始化 IO 口为输入
- 设置 IO 口模式,触发条件,开启 SYSCFG 时钟,设置 IO 口与中断线的映射关系。(在HAL库中可以直接使用HAL_GPIO_Init()进行配置)
- 配置中断优先级(NVIC),并使能中断。(只要有中断就一定要进行NVIC的中断优先级配置)
- 编写中断服务函数。
在HAL库中,中断服务函数并不是简单的我们自己编写的逻辑业务代码
//此函数在中断服务函数中被调用,比如
EXTI0_IRQHandler()
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
{
//清除中断标志位(这个在串口中断中也有,就是每次在中断函数的末尾都要清除中断标志位)
//中断是根据中断标志位来触发的,如果不清楚中断标志位,会一直卡死在你的中断里面不能跳出中断
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin); //回调函数中进行处理我们的逻辑代码
}
}
定时器
STM32F103RC:4个通用定时器(TIM2-5),2个高级定时器(TIM1,TIM8),2个基本定时器(TIM6,TIM7)
定时器中断实现步骤:
- 使能定时器时钟
RCC_APB1PeriphClockCmd()- 初始化定时器
TIM_TimeBaseInit()- 开启定时器中断,配置NVIC
void TIM_ITConfig()
NVIC_Init()- 使能定时器
TIM_Cmd()- 编写中断服务函数
TIMx_IRQHandler()