第二节: 外部中断学习(用CubeMX学习STM32)

STM32外部中断


《用CubeMX学习STM32》

注释 点击上面蓝字进入完整专栏,这个系列所有文章都会整合到这个专栏


STM32外部中断

前言: 关于中断简单介绍

中断的流程:

中断流程图:
在这里插入图片描述

中断方式传送数据具有可以有效提高单片机工作效率, 适合于实时控制系统等优点, 相对于查询方式更为常用。

当CPU处理某件事情的时候, 外部发生的某一事件(如电平的改变、脉冲边沿跳变、定时器/计数器溢出等)请求CPU迅速处理, 于是CPU暂时中断当前的工作, 转去处理发生的事件。 处理完该事件后, 再回到原来中断处, 继续工作。 这样的过程称为中断 上图为中断流程图

这个中断的概念是不是有点晦涩难懂? 主要是这个是书上的内容, 所以不是很形象. 我再解释一遍:想象一个场景,

1、当有一天你正在和川建国同志吃饭(你和他吃饭这个事情就是主程序);
2、突然有个电话打给你, 说有个十五亿的小单子需要你去处理一下(这件事就是中断源),
3、 你停止吃饭, 川建国同志在这等你, 你去处理你的十五亿小合同(就是响应中断请求, 签合同过程就是中断服务程序),
4、处理完合同之后你又回到餐桌继续和他就餐(这就是返回主程序, 然后继续执行主程序).

这样解释是不是清晰一点.

在这里插入图片描述

   关于STM32F407的中断介绍可以看一下原子的或者火哥的pdf, 如果实在看得下去, 看官方手册也行。 这里就不赘述, 通过Cube配置以及编程过程理解这个外部中断会好很多, 通过现象再回去看本质

   同样的, 还使用前面两篇博客所用到的工程即可, 也可以自己新建一个, 当做对自己的测试

2-1. 使用核心板自带按键

操作简介 :    通过板子上的两个按钮控制LED灯的亮灭 WK_UP按键按下则进入中断, 并翻转LED0的状态, KEY0按下时翻转LED1的状态. 两者虽然功能一样, 但却有质的区别

   这里要做的和按键那一篇一样, 只是把其中一个按键改为中断, 而不是作为GPIO_input 所以可以看完上一篇直接看这一篇继续。 点击下方蓝字可以看上一篇的博客

第一节补充: 按键操作(CubeMX加HAL库学STM32系列)


Step1 <CubeMX配置>


RCC&SYS配置这些都不用动, 时钟树的配置也不用动

(1) RCC&SYS以及时钟树配置不用改变

在这里插入图片描述
在这里插入图片描述

(2)更改一下PA0引脚配置:

把WKUP按键对应的PA0引脚模式由GPIO_input改为GPIO_EXIT0, 再把GPIO的配置更改一下即可 具体操作见下图

注 : 如果是用的原来的工程, 只改这个即可, 其他的LED引脚和按键引脚不用动, 如果是自己又新建了一个工程, 那其他引脚按照前面两篇的介绍配置, 然后这个PA0按照这一篇配置就好了, 问题不大

在这里插入图片描述

对应GPIO配置改为下图

在这里插入图片描述

(3)中断NVIC配置
我们设置了中断, 在NVIC里面要记得使能PA0引脚的中断

在这里插入图片描述

NVIC ( Nested Vectored Interrupt Controller ) : 中断向量控制器

在中断向量表里面使能EXIT line0中断

关于抢占优先级和子优先级: 当你使用多个中断的时候会用到这个。 就是为了防止多个中断冲突, 所以需要给他们每个中断排个号, 就不会乱了。 抢占优先级高的先执行, 若抢占优先级相同, 再看子优先级

(4)以上配置完之后就可以Generate CODE

Step2 <程序编写>


(1) 中断服务函数

stm32f4xx_it.c 这个文件里面看到我们要用的中断服务函数
我们要在中断里面做什么事情, 就要写在中断服务函数里面, 然后中断到来之后, 单片机就回去处理中断服务函数里面的工作

在这里插入图片描述
这个函数里面调用了 HAL_GPIO_EXTI_IRQHandler() 这个函数, 这个函数是处理GPIO外部中断的函数 可以看到里面的参数是GPIO_PIN_0, 因为我们用的是PA0即GPIOA的0引脚

Go to definition 一下, 可以看这个函数的定义

/**
  * @brief  This function handles EXTI interrupt request. // 这个功能是处理外部中断请求
  * @param  GPIO_Pin Specifies the pins connected EXTI line // GPIO_Pin指定连接EXTI线的引脚
  * @retval None    // 无返回值
  */
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_Callback()

(2) 中断回调函数
中断回调函数如下图 这个函数是空的, 所以我们可以自己重构这个函数, 在它内部实现我们要做的功能

在这里插入图片描述

我们需要重构中断回调函数

在main.c里面写入我们的代码 :

提示 : 不要忘了把代码写在 /* USER CODE BEGIN / / USER CODE END */ 之间

在这里插入图片描述

/* USER CODE BEGIN 0 */
// 重构中断回调函数  
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	// 判断是否为WKUP引脚(即GPIO_PIN_0)进入中断
	if (WKUP_Pin == GPIO_Pin)
	{
		HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin); // 翻转LED0的的电平状态
		/* 	下面这一句话与上面一句是等价的, 因为LED0是我们给这个引脚起的别名, 在main.h文件里面有对应的宏定义	    */
		//HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_10); 
	}
}

/* USER CODE END 0 */
(3) 主函数
在主函数里面用KEY0做一个一样的功能, 作为对比

在这里插入图片描述

  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	// 在while(1)里面循环扫描, 判断读取的按键引脚状态
	// 下面扫描KEY0按键的引脚信号
    	if (HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == GPIO_PIN_RESET)
		{
			HAL_Delay(10);	// 延时10ms, 做一个软件的消抖, 防止因抖动而检测到按键按下
			if (HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == GPIO_PIN_RESET)
			{
			// 做一个松手检测, 若KEY0一直是RESET(低电平),则一直在死循环
			// 当KEY0位SET才会跳出,进而继续执行下面的对 LED1 的操作
			while(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == GPIO_PIN_RESET);
			HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
		    }
	    }
  }
  /* USER CODE END 3 */

(4) 编译下载到单片机, 看看单片机什么反应

在这里插入图片描述

左边的红色按键是WKUP, 左边的蓝色LED是LED0

在这里插入图片描述


仔细看一下动图中的效果可以发现, 中断的WKUP按键的功能并不是很完美, 这是因为没有消抖导致的, 在中断里面加个软件消抖的程序就可以了。

此外, 虽然两种方式实现的功能是一样的, 但是他们的区别就在于, KEY0翻转LED状态实在while(1)循环里面做的,   这就相当于主函数里面一直循环扫描这个按键的状态, 比较耗费资源.

而WKUP按键按下翻转LED是在中断里面做的,不影响主函数里面做其他事情. 如果以后做的东西要求写很多代码, 最好多多利用中断,这样会更高效。只有当事情来了CPU再去处理,其他时间主函数里面正常做其他事情。 这样既能提高MCU效率, 也不会让自己的代码全部写成一坨在主函数里面


破晓之日, 你的所有努力都会助你看到黎明的第一缕阳光。
请坚信: 你是一道光, 也是一把剑 ! 你终将刺破寒冰和黑夜, 重新定义你的人生 !

Author : 李光辉
date : Sun Dec 29 20:54:17 CST 2019
blog ID: Kevin_8_Lee
blog site : https://blog.csdn.net/Kevin_8_Lee/
  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值