中断和事件

在STM32微控制器中,中断和事件是用于处理外部事件和内部状态改变的重要机制。它们允许微控制器在特定条件下停止当前执行的任务,转而处理更为紧急或重要的任务。以下是关于STM32中断和事件的一些基本信息:

  • 中断(Interrupts):

中断是在微控制器执行某个任务时,突然发生的外部事件或者条件改变,需要立即引起处理的机制。当中断事件发生时,微控制器会立即暂停当前执行的指令,保存当前上下文,然后跳转到中断处理程序(也称为中断服务例程)执行相应的处理。一旦中断处理程序完成,微控制器会恢复之前的上下文并继续之前的任务。

在STM32中,不同的外设和引脚可以配置成产生不同类型的中断,比如外部中断、定时器中断、串口中断等。使用中断可以有效地响应实时性要求较高的事件,如传感器数据的读取、通信数据的处理等。

  • 事件(Events):

事件是STM32微控制器内部状态的变化或触发的标志。这些状态变化可能与外设的工作有关,也可能与软件中的状态转换有关。STM32提供了事件监听和产生的功能,使得某些操作可以在特定事件发生时自动触发。

中断优先级

STM32 中的中断优先级可以分为:抢占式优先级和响应优先级,响应优先级也称子优先级, 每个中断源都需要被指定这两种优先级。

抢占式优先级和响应优先级的区别:

  • 抢占优先级:抢占优先级高的中断可以打断正在执行的抢占优先级低的中断。
  • 响应优先级:抢占优先级相同,响应优先级高的中断不能打断响应优先级低的中断。

HAL库常用中断函数

中断基础函数位于 stm32f4xx_hal_exti.c文件中

void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)

 4位二进制优先级分组

void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)

 设置某个中断的优先级

void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)

 启用某个中断

void HAL_NVIC_DisableIRQ(IRQn_Type IRQn)

 禁用某个中断

uint32_t HAL_NVIC_GetPriorityGrouping(void)

 获取当前优先级分组策略

void HAL_NVIC_GetPriority(IRQn_Type IRQn, uint32_t PriorityGroup, uint32_t *pPreemptPriority, uint32_t *pSubPriority)

 获取某个中断的优先级

void HAL_EXTI_ClearPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)

清除某个挂起标志位

uint32_t HAL_EXTI_GetPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)

设置某个挂起标志位

基于CUBEMX生成的不同外设中断文件 stm32f4xx_it.c。函数void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)和函数void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)在cubemx配置完成后由系统自动生成。

HAL库中断回调机制

  • 在文件stm32f4xx_it.c 中,由cubemx 生成已经启动的中断ISR代码框架 例:EXIT0中的中断生成 ISR函数 为:EXIT0_IRQHandler()
  • 在ISR函数中,执行HAL库中为该函数定义的通用处理函数 例:外部中断的通用函数为 HAL_GPIO_EXIT_IROHandler()。在通用函数中,会自动进行中断时间来源的判断(一个中断号一般有多个中断事件源)、中断标志位的判断和清除,并且调用与中断事件源相关的中断回调函数。
  • 在中断回调函数中,用户可以实现中断处理需求。

例:CUBEMX外部中断EXIT配置

配置顺序:

  • 配置外部中断对应引脚属性。

  • 配置外部中断组,开启外部中断。

  • 编写外部中断函数。

使用cubemx 生成代码

stm32f4xx_it.c中的外部中断函数

复制代码
void EXTI0_IRQHandler(void)

{

/* USER CODE BEGIN EXTI0_IRQn 0 */

/* USER CODE END EXTI0_IRQn 0 */

HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

/* USER CODE BEGIN EXTI0_IRQn 1 */

/* USER CODE END EXTI0_IRQn 1 */

}
复制代码

 

在GPIO文件stm32f4xx_hal_gpio.c中找到对应外部中断的若函数进行重写

复制代码
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

/* Prevent unused argument(s) compilation warning */

UNUSED(GPIO_Pin);

/* NOTE: This function Should not be modified, when the callback is needed,

the HAL_GPIO_EXTI_Callback could be implemented in the user file

*/

}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

用户代码

}
复制代码

 

Q&A

STM32 HAL库中 为什么外部中断需要清除中断标志位 而定时器中断不需要?

在STM32 HAL库中,外部中断和定时器中断之所以需要处理的方式不同,涉及到它们触发和处理的机制。让我们来详细解释一下:

外部中断:

外部中断是由外部事件触发的,例如按下按钮、传感器触发等。当这些事件发生时,引脚上的电平变化(上升沿、下降沿或双边沿)会产生一个中断请求。在处理外部中断时,中断请求会导致中断处理程序被调用。为了防止多次触发同一个中断请求,需要在处理程序中清除中断标志位。如果不清除中断标志位,中断控制器会一直认为有中断请求,从而导致中断处理程序被重复调用。

定时器中断:

定时器中断是通过定时器计数器的溢出或者达到特定计数值来触发的。当定时器计数达到设定的值时,会产生定时器中断请求,从而调用中断处理程序。与外部中断不同,定时器中断在处理程序被调用后,不需要手动清除中断标志位。这是因为在中断处理程序执行完毕后,硬件会自动重置定时器的中断标志位。这样,下一次定时器计数达到设定值时,会再次触发中断请求。

因此,区别在于外部中断需要手动清除中断标志位以避免重复触发,而定时器中断则由硬件自动处理中断标志位的重置。