Timer与按键消抖的应用

本小节教你使用 STM32CubeMX 软件配置 MiaowLabs-STM32F1-Micro 核心板按键引脚的底层驱动,并使用 MDK-ARM 5.17 编写代码识别用户按键的单击动作,实现使用按键控制 LED 的亮灭功能。

在上一小节中,我们使用 STM32CubeMX 软件配置 MiaowLabs-STM32F1-Micro 核心板的底层驱动,并使用 MDK-ARM 5.17 编写代码点亮板子上的的蓝色 LED。在这一小节,我将继续教你实现使用按键控制 LED 的亮灭功能。

预先了解

MiaowLabs-STM32F1-Micro 核心板板上面有一颗用户按钮 是跟 STM32 的 PA11 引脚相连。我们可以通过编写代码识别按键的单击,当 PA11 引脚为低电平时,识别为按下按键;当 PA11 引脚为高电平时,识别为按下按键。

具体步骤

进入我们上一小节修改过的 MiaowLabs-Demo 文件夹,找到 MiaowLabs-Demo.ioc 工程文件,双击,打开工程。在 Pinout&Configuration 界面中的芯片中点击 PA11,并将其配置为 GPIO_Input。

在左侧的 System Core 下拉菜单中选择 GPIO,然后在 GPIO Mode and Configuration 中对 PA11 引脚进行配置,GPIO mode 代表 GPIO 引脚模式,在这里设置为输入模式;GPIO Pull-up/Pull-down 即 GPIO 上拉或下拉,根据硬件实际情况,在这里设置为上拉;User Label 即用户标签,因为 PA11 在这里的功能是识别按键,所以输入 Button 作为标签。

点击 GENERATE CODE,重新生成代码。

因为通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。

消抖是为了避免在按键按下或是抬起时电平剧烈抖动带来的影响。按键的消抖,可用硬件或软件两种方法,在实际的设计中,为了节省硬件成本,大多数情况会选择使用软件消抖。

延时消抖

软件消抖,即检测出按键闭合后执行一个延时程序,5ms~10ms 的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。当检测到按键释放后,也要给 5ms~10ms 的延时,待后沿抖动消失后才能转入该键的处理程序。

以前常用的消抖算法往往就是:判断按下->延时->再次判断是否按下->是,执行/否,退出。

最简单的消抖原理,就是当检测到按键状态变化后,先等待一个 10ms 左右的延时时间,让抖动消失后再进行一次按键状态检测,如果与刚才检测到的状态相同,就可以确认按键已经稳定的动作了。

利用定时器消抖

利用定时器消抖算法:通过 SysTick 中断每1ms对按键进行扫描,当检测到连续的稳定无抖动电平信号(长度可设置)之后,才进行相应的逻辑操作。

我们启用一个定时中断,每 1ms 进一次中断,扫描一次按键状态并且存储起来,连续扫描 25 次后,看看这连续 25 次的按键状态是否是一致的。25 次按键的时间是 25ms,这 25ms 内如果按键状态一直保持一致,那就可以确定现在按键处于稳定的阶段,而非处于抖动的阶段。

我们在上一小节中已经对 SYS 进行了配置。

在 STM32CubeMX 中,默认 SysTick 中断为 1ms。 我们可以打开 MDK-ARM 工程,在左侧 Drivers/STM32F1xx_HAL_Driver 文件夹的 stm32f1xx_hal.c 文件中找到 SysTick 的初始化。

函数里面有一句注释: /* Configure the SysTick to have interrupt in 1ms time basis*/,翻译过来就是,将 SysTick 配置为 1ms 中断。也就是说,经过此函数,SysTick 定时器被初始化为 1ms 的时基单元,即每毫秒进入一次 Systick 中断。

我们可以在左侧 Application/User 文件夹的 stm32f1xx_it.c 文件中找到 SysTick 中断服务函数。

里面只有一个 HAL_IncTick() 函数,我们右键转跳到该函数可以看到该函数的定义。

每毫秒 uwTick 加一,用于计算 Systick 产生的节拍数。

在 HAL_IncTick 函数的下方有一个 HAL_GetTick(void) 函数,主要用于获取当前节拍,如果内核正常运行,则 uwTick 的值即为已经经过的 ms 数。

这里顺便提及一下 HAL 库的延时函数 HAL_Delay() 。在左侧 Drivers/STM32F1xx_HAL_Driver 文件夹的 stm32f1xx_hal.c 文件中找到 HAL_Delay() 函数。

可以看到 HAL_Delay() 函数其实就是通过 HAL_GetTick() 函数数节拍以确定精准的延时。

回到按键消抖的主题,既然 STM32CubeMX 已经默认设置 Systick 为 1ms 中断,那么我们可以直接利用起来。打开 MDK-ARM 工程,按下组合键 Ctrl+N(按住 Ctrl 键再按 N 键),新建一个文件,再按下组合键 Ctrl+S,文件名改为 button.c,保存到 MiaowLabs-DEMO 的 Src 文件夹里。来到这里,我们虽然新建了button.c 源文件,但是还没有把该文件加入到 MDK-ARM 工程里。我们在 MDK-ARM 工程界面左侧 Project 栏目双击 Application/User 文件夹,把 button.c 加进来。

双击 button.c 文件,把下面代码敲进去。

再新建一个文件 button.h 头文件,把文件保存到 Inc 文件夹。然后,把下面代码敲进去。

打开 stm32fxx_it.c 文件,在 /* USER CODE BEGIN Includes *//* USER CODE END Includes */ 之间加入 #include "button.h"。

在 stm32fxx_it.c 文件里面 SysTick_Handler() 函数里加入按键扫描函数 ButtonScan()。

在左侧 Application/User 文件夹里打开 main.c 函数,在主循环里面加入以下代码:

这段代码的意思就是:如果按键状态标志为 1 ,则代表按键被按下了,这时候进行 LED 电平翻转。

在左侧 Application/User 文件夹里点开 main.c 函数左侧的加号,找到 main.h 头文件,并把#include "button.h"头文件加进去。

代码已经编写好了。这时候,点击编译按钮,会提示没有错误和警告。

把代码烧录进 MiaowLabs-STM32F1-Micro 核心板,然后按下用户按键,可以发现按一下 LED 会亮,再按一下 LED 就会灭掉。就这样,我们实现了通过按键控制 LED 亮灭的功能。

最后更新于

这有帮助吗?