第13章 GPIO输入—按键检测
本章参考资料:《STM32F76xxx参考手册》、库帮助文档《STM32F779xx_User_Manual.chm》。
按键检测使用到GPIO外设的基本输入功能,本章中不再赘述GPIO外设的概念,如您忘记了,可重读前面“GPIO框图剖析”小节,STM32 HAL库中GPIO初始化结构体GPIO_TypeDef的定义与“定义引脚模式的枚举类型”小节中讲解的相同。
13.1 硬件设计
按键机械触点断开、闭合时,由于触点的弹性作用,按键开关不会马上稳定接通或一下子断开,使用按键时会产生图 13-1中的带波纹信号,需要用软件消抖处理滤波,不方便输入检测。本实验板连接的按键带硬件消抖功能,见图 13-2,它利用电容充放电的延时,消除了波纹,从而简化软件的处理,软件只需要直接检测引脚的电平即可。

图 13-1 按键抖动说明图

图 13-2 按键原理图
从按键的原理图可知,这些按键在没有被按下的时候,GPIO引脚的输入状态为低电平(按键所在的电路不通,引脚接地),当按键按下时,GPIO引脚的输入状态为高电平(按键所在的电路导通,引脚接到电源)。只要我们检测引脚的输入电平,即可判断按键是否被按下。
若您使用的实验板按键的连接方式或引脚不一样,只需根据我们的工程修改引脚即可,程序的控制原理相同。
12.2 软件设计
同LED的工程,为了使工程更加有条理,我们把按键相关的代码独立分开存储,方便以后移植。在“工程模板”之上新建“bsp_key.c”及“bsp_key.h”文件,这些文件也可根据您的喜好命名,这些文件不属于STM32 HAL库的内容,是由我们自己根据应用需要编写的。
12.2.1 编程要点
1. 使能GPIO端口时钟;
2. 初始化GPIO目标引脚为输入模式(引脚默认电平受按键电路影响,浮空/上拉/下拉均没有区别);
3. 编写简单测试程序,检测按键的状态,实现按键控制LED灯。
12.2.2 代码分析
1. 按键引脚宏定义
同样,在编写按键驱动时,也要考虑更改硬件环境的情况。我们把按键检测引脚相关的宏定义到 “bsp_key.h”文件中,见代码清单 12-1。
代码清单 13-1 按键检测引脚相关的宏
//引脚定义
/*******************************************************/
#define KEY1_PIN GPIO_Pin_0
#define KEY1_GPIO_PORT GPIOA
#define KEY1_GPIO_CLK () __GPIOA_CLK_ENABLE() #define KEY2_PIN GPIO_Pin_13
#define KEY2_GPIO_PORT GPIOC
#define KEY2_GPIO_CLK() __GPIOC_CLK_ENABLE()
/*******************************************************/
以上代码根据按键的硬件连接,把检测按键输入的GPIO端口、GPIO引脚号以及GPIO端口时钟封装起来了。
2. 按键 GPIO初始化函数
利用上面的宏,编写按键的初始化函数,见代码清单 13-2。
代码清单 13-2 按键GPIO初始化函数
/**
2 * @brief 配置按键用到的I/O口
3 * @param 无
4 * @retval 无
5 */
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; /*开启按键GPIO口的时钟*/
KEY1_GPIO_CLK_ENABLE();
KEY2_GPIO_CLK_ENABLE();
/*选择按键的引脚*/
GPIO_InitStructure.Pin = KEY1_PIN; /*设置引脚为输入模式*/
GPIO_InitStructure.Mode = GPIO_MODE_INPUT; /*设置引脚不上拉也不下拉*/
GPIO_InitStructure.Pull = GPIO_NOPULL; /*使用上面的结构体初始化按键*/
HAL_GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure); /*选择按键的引脚*/
GPIO_InitStructure.Pin = KEY2_PIN; /*使用上面的结构体初始化按键*/
HAL_GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure); }
同为GPIO的初始化函数,初始化的流程与“LED GPIO初始化函数”章节中的类似,主要区别是引脚的模式。函数执行流程如下:
(1) 使用GPIO_InitTypeDef定义GPIO初始化结构体变量,以便下面用于存储GPIO配置。
(2) 调用宏定义函数KEY1_GPIO_CLK_ENABLE(),KEY2_GPIO_CLK_ENABLE()来使能按键的GPIO端口时钟。
(3) 向GPIO初始化结构体赋值,把引脚初始化成浮空输入模式,其中的Pin使用宏“KEYx_PIN”来赋值,使函数的实现方便移植。由于引脚的默认电平受按键电路影响,所以设置成“浮空/上拉/下拉”模式均没有区别。
(4) 使用以上初始化结构体的配置,调用HAL_GPIO_Init函数向寄存器写入参数,完成GPIO的初始化,这里的GPIO端口使用“KEYx_GPIO_PORT”宏来赋值,也是为了程序移植方便。
(5) 使用同样的初始化结构体,只修改控制的引脚和端口,初始化其它按键检测时使用的GPIO引脚。
3. 检测按键的状态
初始化按键后,就可以通过检测对应引脚的电平来判断按键状态了,见代码清单 13-3。
代码清单 13-3 检测按键的状态
/** 按键按下标置宏
2 * 按键按下为高电平,设置 KEY_ON=1, KEY_OFF=0
3 * 若按键按下为低电平,把宏设置成KEY_ON=0 ,KEY_OFF=1 即可
4 */
#define KEY_ON 1
#define KEY_OFF 0 /**
9 * @brief 检测是否有按键按下
10 * @param GPIOx:具体的端口, x可以是(A...K)
11 * @param GPIO_PIN:具体的端口位, 可以是GPIO_PIN_x(x可以是0...15)
12 * @retval 按键的状态
13 * @arg KEY_ON:按键按下
14 * @arg KEY_OFF:按键没按下
15 */
uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
{
/*检测是否有按键按下 */
if (HAL_GPIO_ReadPin(GPIOx,GPIO_Pin) == KEY_ON ) {
/*等待按键释放 */
while (HAL_GPIO_ReadPin(GPIOx,GPIO_Pin) == KEY_ON);
return KEY_ON;
} else
return KEY_OFF;
}
在这里我们定义了一个Key_Scan函数用于扫描按键状态。GPIO引脚的输入电平可通过读取IDR寄存器对应的数据位来感知,而STM32 HAL库提供了库函数HAL_GPIO_ReadPin来获取位状态,该函数输入GPIO端口及引脚号,函数返回该引脚的电平状态,高电平返回1,低电平返回0。Key_Scan函数中以HAL_GPIO_ReadPin的返回值与自定义的宏“KEY_ON”对比,若检测到按键按下,则使用while循环持续检测按键状态,直到按键释放,按键释放后Key_Scan函数返回一个“KEY_ON”值;若没有检测到按键按下,则函数直接返回“KEY_OFF”。若按键的硬件没有做消抖处理,需要在这个Key_Scan函数中做软件滤波,防止波纹抖动引起误触发。
4. 主函数
接下来我们使用主函数编写按键检测流程,见代码清单 13-4。
代码清单 13-4 按键检测主函数
/**
2 * @brief 主函数
3 * @param 无
4 * @retval 无
5 */
int main(void)
{
/* 系统时钟初始化成216 MHz */
SystemClock_Config();
/* LED 端口初始化 */
LED_GPIO_Config(); /*初始化按键*/
Key_GPIO_Config(); /* 轮询按键状态,若按键按下则反转LED */
while () {
if ( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON ) {
/*LED1反转*/
LED1_TOGGLE;
} if ( Key_Scan(KEY2_GPIO_PORT,KEY2_PIN) == KEY_ON ) {
/*LED2反转*/
LED2_TOGGLE;
}
}
}
代码中设置系统时钟为216MHz,初始化LED灯及按键后,在while函数里不断调用Key_Scan函数,并判断其返回值,若返回值表示按键按下,则反转LED灯的状态。
13.1.1 下载验证
把编译好的程序下载到开发板并复位,按下按键可以控制LED灯亮、灭状态。
第13章 GPIO输入—按键检测的更多相关文章
- 第12章 GPIO输入—按键检测
第12章 GPIO输入—按键检测 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fi ...
- 第12章 GPIO输入-按键检测—零死角玩转STM32-F429系列
第12章 GPIO输入—按键检测 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fi ...
- GPIO 输入—按键检测
这里要用到一定的模电知识.电容两端电压不能突变,电感两端电流不能突变.这里利用了电容的放电延时实现硬件消抖.按键按下会有抖动,波形有毛刺,使得高低电平显现不明显,而按键按下时,电容放电一下,马上又被充 ...
- GPIO输入—按键检测(开关控制小灯)
本次的代码全是在上次代码之上添加的. 1.user下新建文件夹key,新建bsp_key.h bsp_key.c文件. 2.keil项目添加bsp_key.c,魔术棒C/C++中include pat ...
- 第33章 TIM—电容按键检测—零死角玩转STM32-F429系列
第33章 TIM—电容按键检测 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fir ...
- 第13章 GPIO—位带操作
第13章 GPIO—位带操作 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fire ...
- 【C语言学习】《C Primer Plus》第13章 文件输入/输出
学习总结 1.文件函数原型1: FILE* fopen(char *filename, char *openmode); //打开文件,返回文件指针 filename:文件名,更确切地说,是包含文件 ...
- 第 13 章 文件输入/输出 (标准I/O)
/*-------------------------- count.c -- 使用标准 I/O --------------------------*/ #include <stdio.h&g ...
- 第13章 GPIO-位带操作—零死角玩转STM32-F429系列
第13章 GPIO—位带操作 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fire ...
随机推荐
- [Scala] Currying
Currying是一種函數式編程技巧, 指的是把接受多個參數的函數變換成接受一個單一參數的函數. 以一個簡單的例子在Scala中實現.. def f(a:Int, b:Int)={ a+b } //f ...
- Nginx启动关闭和重启、文档直接下载不阅览
nginx启动相关 启动:sbin/nginx -c conf/nginx.conf 关闭:sbin/nginx -s stop 重启(重新加载配置文件):sbin/nginx -s reload 检 ...
- JVM 类加载全过程
类加载机制 - JVM把class文件加载到内存中 并对数据进行 校验,解析,初始化,最终形成JVM可以直接使用的java类型的过程 详细过程 加载→ 验证→ 准备→ 解析 → 初始化→ 使用 → ...
- Nginx+Keepalived配置
1. Nginx安装 (1) 环境:分别在2台服务器上部署nginx且步骤一致: 如192.138.86.1和192.138.86.2 (2) 下载官网最新稳定版,地址:https://nginx.o ...
- React.js 小书 Lesson12 - state vs props
作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson12 转载请注明出处,保留原文链接和作者信息. 我们来一个关于 state 和 props 的 ...
- 微信小程序支付c#后台实现
今天为大家带来比较简单的支付后台处理 首先下载官方的c#模板(WxPayAPI),将模板(WxPayAPI)添加到服务器上,然后在WxPayAPI项目目录中添加两个“一般处理程序” (改名为GetOp ...
- 人民币金额大小写Js转换
/** * 数字转中文 * @param dValue * @returns */ function chineseNumber(dValue) { var maxDec = 2; // 验证输入金额 ...
- MVC3.0与MVC2.0的区别
昨天面试时第一回用MVC2.0做了一个简单的增删改查功能的测试.想一下用了一年多的MVC3.0,对这两个版本不同之处做以下几点总结: 最明显的是MVC3.0较MVC2.0而言,多了Razor视图: 1 ...
- 使用java applet通过签名访问客户端串口
前端时间公司有需求要访问客户端串口读取电子称的数据,通过网上资料,决定使用applet通过电子签名的形式实现. 1.先写applet:这里我是使用RXRTcomm.jar LocalFileApple ...
- 成长之路--Docker入门
简介 Docker是一种新兴的虚拟化技术,能够一定程度上的代替传统虚拟机. Docker版本 Docker 划分为CE 和EE.CE 即社区版(免费,支持周期三个月),EE 即企业版,强调安全,付费使 ...