>[success] **技术支持说明**
> 1.**客服**提供简单的技术支持,一般自主学习为主
> 2.可到官方问答社区中提问:[**去提问**](https://bbs.csdn.net/forums/nb-iot)
> 3.工程师**会尽快**解答社区问题,但他们是一线开发,【**难以保证**】解答时效,解答辛苦,感谢理解!
<br/>
## **按键原理简介**
  在LED相关课程中,把GPIO配置为输出模式,然后通过控制该GPIO输出高/低电平来控制LED的亮/灭。然而,与之相反,按键是一种被动器件,即由外界把按键相关的信号输入到主控芯片中,因此需要把GPIO配置为输入模式。
###
**电路原理简介**
配套的开发板带有一个名为“PA0”的按键,如下图所示。
![](https://img.kancloud.cn/7f/25/7f255c0346cc531b0a02fc34645643c1_1671x1884.png =200x)
###
其原理图如下所示。
![](https://img.kancloud.cn/f9/1b/f91b89a1f9375403b7db7d1a450ad00a_673x236.png =500x)
>[warning] 如您未能看懂此原理图,需要补充一下相关知识。
<br/>
从原理图中可以看出,此按键与STM32的PA0引脚相连接。在把PA0配置为输入模式后,当按键被按下时,PA0接地,即输入低电平。与此同时,可以通过内部上拉的方式实现没有按下时即输入高电平。此时,程序通过检测PA0输入电平即可检测按键是否被按下:
* 按键没有被按下时,PA0输入高电平
* 按键被按下后,PA0输入低电平
>[info] 如果读者不了解何谓内部上拉,可暂时跳过
<br/>
## **按键HAL API 设计**
通过前面的原理分析,可以知道按键是一种被动器件,需要检测PA0的输入电平高低变化。在设计此类型API时,可以使用注册回调的思想,即上层应用在HAL中注册已给回调函数,一旦HAL检测到按键按下,就会回调给上层应用,如图所示。
![](https://img.kancloud.cn/cc/c9/ccc9a3c8665bdbd80de9b3e0428ebf47_464x481.png =250x)
###
接下来通过代码来讲解这个设计。
<br/>
**编写代码**
笔者在本节课配套的源代码中新建了 hal\_button.h 和 hal\_button.c文件,如图所示。
![](https://img.kancloud.cn/6c/65/6c655c550a158648a25887de4122061d_600x1056.png =200x)
###
打开本节课配套的工程,笔者把hal\_button.c以及必要的标准库文件添加进工程了,如图所示。
![](https://img.kancloud.cn/8f/cb/8fcb72807c8aef9309099f80a2faaefb_375x535.png =250x)
<br/>
hal_button.h文件的代码如下:
```
#ifndef __HAL_BUTTON_H__
#define __HAL_BUTTON_H__
/*定义按键连接的GPIO口PA0*/
#define HAL_BUTTON_PORT GPIOA
#define HAL_BUTTON_PIN GPIO_Pin_0
/*定义GPIOA对应的时钟 */
#define HAL_BUTTON_CLOCK RCC_AHBPeriph_GPIOA
#define HAL_BUTTON_TRIGGER_LEVEL 0
/*
* 按键初始化
* @param onClick - 按键回调函数,当按键被按下时执行此函数
*/
void halButtonInit(void (*onClick)(void));
/*
* 检测到按键按下时,执行回调回调函数
*/
void halButtonPoll(void);
#endif /* #ifndef __HAL_BUTTON_H__ */
```
<br/>
hal_button.c文件的代码如下:
###
```
#include "hal_button.h"
#include "hal_system.h"
#include "stm32f0xx_gpio.h"
static void (*halButtonOnClick)(void) = 0;
/*
* 按键初始化
* @param onClick - 按键回调函数,当按键被按下时执行此函数
*/
void halButtonInit(void (*onClick)(void))
{
halButtonOnClick = onClick;//保存回调函数
GPIO_InitTypeDef buttonGPIO;//定义GPIO配置
buttonGPIO.GPIO_Mode = GPIO_Mode_IN;//配置为输入模式
buttonGPIO.GPIO_PuPd = GPIO_PuPd_UP,//配置为上拉
buttonGPIO.GPIO_Speed = GPIO_Speed_2MHz;//速率为2MHz
buttonGPIO.GPIO_Pin = HAL_BUTTON_PIN;//引脚
RCC_AHBPeriphClockCmd(HAL_BUTTON_CLOCK, ENABLE);//使用按键时钟
GPIO_Init(HAL_BUTTON_PORT, &buttonGPIO);//初始化PA0
}
/*
* 检测到按键按下时,执行回调函数
*/
void halButtonPoll(void)
{
/* 如果按键没有被按下,如果没有则返回*/
if (GPIO_ReadInputDataBit(HAL_BUTTON_PORT, HAL_BUTTON_PIN) != HAL_BUTTON_TRIGGER_LEVEL) return;
/* 延迟10ms,去除机械按键抖动 */
halSystemDelayUs(1000 * 10);
/* 再次检测按键是否被按下,如果没有则返回*/
if (GPIO_ReadInputDataBit(HAL_BUTTON_PORT, HAL_BUTTON_PIN) != HAL_BUTTON_TRIGGER_LEVEL) return;
/* 等待按键松开 */
while(GPIO_ReadInputDataBit(HAL_BUTTON_PORT, HAL_BUTTON_PIN) == HAL_BUTTON_TRIGGER_LEVEL) halSystemDelayUs(1000);
/* 如果定义回调函数,则调用回调函数 */
if (halButtonOnClick != 0) halButtonOnClick();
}
```
**处理机械按键抖动**
上述代码包含了按键抖动的处理,对其简单讲解一下。由于按键内部采用了弹簧,所以当按键被按下或松开的时候,会产生一定的震动,这种震动可以称为机械抖动。这种机械抖动会导致电平的抖动,如下图所示。
![](https://img.kancloud.cn/bf/f5/bff52fc67f3feab02d1677a500e74037_582x324.png =300x)
###
上图展示了按钮从按下到松开这个过程的电平变化。按键被按下时产生的抖动称为前沿抖动,松开时产生的是后沿抖动。这个抖动时间一般持续5~10ms。因此在代码上当检测到按钮被按下后,需要延后10ms后再检测一次按钮是否真的被按下。
<br/>
## **使用按键 HAL API**
编写好按键 HAL API后,按键的使用非常简单。在配套工程的main.c文件中添加如下代码:
```
/*
* 按键回调函数,当按键被按下后即执行此函数
*/
static void buttonOnClick()
{
halLedToggle();//反转LED灯的亮灭状态
}
int main(void)
{
halSystemInit();//系统初始化
halLedInit();//LED初始化
/*按键初始化,并且传入了回调函数*/
halButtonInit(buttonOnClick);
/*使用while循环来持续检测按键是否被按下*/
while (1)
{
halButtonPoll();
}
}
```
上述代码实现了当按键别按下并松开后,反转LED灯的状态,代码非常简洁!
<br/>
<br/>
## **商务合作**
如有以下需求,可扫码添加管理员好友,注明“**商务合作**”
* 项目定制开发,技术范围:**NB-IoT**、**CATn(4G)**、**WiFi**、**ZigBee**、**BLE Mesh**以及**STM32**、**嵌入式Linux**等;
* 入驻平台,成为讲师;
* 接项目赚外快;
* 善学坊官网:[www.sxf-iot.com](https://www.sxf-iot.com/)
![](https://img.kancloud.cn/ca/73/ca739f92cab220a3059378642e3bd502_430x430.png =150x)
(非商务合作**勿扰**,此处**非**技术支持)
- 课程介绍
- 配套资源下载
- 配套开发套件简介
- 简介
- 硬件组成 & 技术参数
- 电路原理图 & PCB图
- 拨码开关使用说明
- 第一部分:无线通信 开发指南
- 1.1.1 NB-IoT:技术简介
- 1.1.2 NB:CH34x USB转串口驱动安装
- 1.1.3 NB:AT 指令开发与测试
- 1.1.4 NB:基础指令集简介
- 1.1.5 NB:云端服务器
- 1.1.5.1 PuTTY 简介与安装
- 1.1.5.2 登录云端服务器
- 1.1.6 NB:移远官方工具简介
- 1.1.7 NB:使用UDP协议与云端服务器通信
- 1.1.8 NB:使用TCP协议与云端服务器通信
- 1.1.9 NB:使用MQTT协议与云端服务器通信
- 进阶课程
- 第二部分:STM32 开发指南
- 2.1 搭建开发环境
- 2.1.1 Keil MDK 简介与安装
- 2.1.2 STM32 Pack 简介与安装
- 2.1.3 CH34x 驱动简介与安装
- 2.1.4 其他开发工具
- 2.2 STM32 开发基础
- 2.2.1 新建工程
- 2.2.2 实现第1个程序
- 2.2.3 Hex 文件烧录详解
- 2.3 移植官方标准工程模板
- 2.4 GPIO实验——LED灯
- 2.5 系统延时应用
- 2.6 GPIO实验——按键
- 2.7 GPIO中断实验——按键触发
- 2.8 使用定时器TIM3
- 2.9 串口通信实验
- 2.10 ADC 实验
- 2.11 OLED显示器实验
- 2.12 SDK 设计思想
- 2.13 SDK 架构解析
- 2.14 多任务应用
- 2.15 输入型任务:按键输入
- 2.16 输入型任务:串口接收
- 课外篇:项目实战
- 基于STM32+NB-IoT的温湿度采集
- 系统简介
- 系统搭建
- 系统详解
- 1.代码编译与架构说明
- 2.DHT11温湿度传感器
- 3. 数据通信任务说明
- 版权声明与免责声明