stm32中断的基础知识

文章目录

    • 中断
      • 中断的硬件实现
      • stm32的外部中断
    • HAL库的中断实现
    • 外部中断的回调函数
    • 使用外部中断检测按键(示例)
      • 设置Cube外设
      • 中断的代码理解
      • 代码编写
    • 参考资料

中断

某些事件可能需要CPU暂停目前的程序优先处理

实现CPU暂停当前的程序并优先处理某一事件的机制称作中断

处理这一事件的程序叫做中断服务程序(Interrupt Handler)

中断的硬件实现

内部或外部信号产生中断

—>程序跳转到某一特定地址(中断向量)

//不同的中断可能会对应同一地址,此后在程序中需要进行判定

—>程序从中断向量跳转到对应的中断服务程序

//此时会将原来正在使用的重要数据压入堆栈(某一特定的内存空间)

—>执行完毕后返回原来被打断的位置

//堆栈中的数据被还原,保证原来的程序正常执行

stm32的外部中断

  • 外部中断可由GPIO输入上升沿(0->1跳变)和/或下降沿(1->0跳变)触发
  • 最多16个外部中断
    • 每组GPIO相同编号的pin共享一个外部中断
    • 每个GPIO都可以被配置为外部中断

HAL库的中断实现

首先Cube会生成一个stm32xx_it.c(即中断服务程序入口,中断向量处跳转指向的地址)

HAL库会预先处理中断,判断中断类型

//在中断服务程序入口处,HAL库会调用自己的一个函数
//在判定完中断类型后会调用对应的回调函数(即Callback)
//Callback用_week定义,可以被用户改写

外部中断的回调函数

void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin)

在这里插入图片描述

可以在任意程序文件中重新定义这个函数

外部中断产生时,HAL库处理完中断会调用这个函数

//传入参数是具体产生中断的引脚,需要使用GPIO_Pin宏定义判定
//若需判定中断由上升沿还是下降沿产生,可以读取当前GPIO电平

使用外部中断检测按键(示例)

设置Cube外设

打开Cube,把基本外设以及时钟树设置完后

把PA0设置为GPIO_EXTI0,因为这是 A组GPIO 的第 0 号引脚所以其所属的中断向量为 EXTI0

在旁边外设设置中的NVIC中的EXTI line0 interrupt勾上,这样才会产生中断

在GPIO选项中PA0引脚被激活后可以在GPIO mode中选择上升沿触发还是下降沿触发

这次改成由上升沿和下降沿触发

中断的代码理解

用keil5打开代码后打开stm32f4xx_it.c文件,

里面有Cube自动生成的void xxFault_Handler(void)函数,

这些函数代表芯片出错后会进入这些中断,

这些函数里面都有一个while(1)循环,这样在出错后可以直接把程序卡死停止执行

在文件最下面有 EXTI0_IRQHandler

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 */
}

在产生外部中断后,程序就会跳转到这个地方

其中有一个hal库函数

 HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);

在stm32f4xx_hal_gpio.c中可以找到这个函数

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}

这个函数就代表如果它读到低电平,即按键按下后产生中断

__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);

这个函数会把中断的标志物清除

HAL_GPIO_EXTI_Callback(GPIO_Pin);

接着就会调用回调函数

在后面会有一个__weak函数

__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
   */
}

即该回调函数可以被再次声明,即会覆盖掉自动生成的函数

在中断回调函数中编写在此次中断中需要执行的功能即可。

代码编写

在main.c

在/* USER CODE BEGIN 4 */

/* USER CODE END 4 */中写入我们重定义的函数

即我们可以在这里添加我们的中断回调函数

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
		if(GPIO_Pin==GPIO_PIN_0)//判断是否为外部中断0的回调
			{
				if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_SET)
					{
						HAL_GPIO_WritePin(GPIOH,GPIO_PIN_12,GPIO_PIN_RESET);	
					}
				else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
					{
						HAL_GPIO_WritePin(GPIOH,GPIO_PIN_12,GPIO_PIN_SET);
					}	//移植的电灯代码
			}
};
/* USER CODE END 4 */

然后就可以进行编译烧录。

参考资料

CH1.3 GPIO 第3讲 中断与EXTI【南工骁鹰嵌入式软件培训】

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

书阁下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值