第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 按键检测引脚相关的宏

1 //引脚定义
 2 /*******************************************************/
 3 #define KEY1_PIN                  GPIO_Pin_0
 4 #define KEY1_GPIO_PORT            GPIOA
 5 #define KEY1_GPIO_CLK ()     __GPIOA_CLK_ENABLE()
6
 7 #define KEY2_PIN                  GPIO_Pin_13
 8 #define KEY2_GPIO_PORT            GPIOC
 9 #define KEY2_GPIO_CLK()           __GPIOC_CLK_ENABLE()
10 /*******************************************************/

以上代码根据按键的硬件连接,把检测按键输入的GPIO端口、GPIO引脚号以及GPIO端口时钟封装起来了。

2. 按键 GPIO初始化函数

利用上面的宏,编写按键的初始化函数,见代码清单 13-2。

代码清单 13-2 按键GPIO初始化函数

1 /**
 2   * @brief  配置按键用到的I/O口
 3   * @param  无
 4   * @retval 无
 5   */
 6 void Key_GPIO_Config(void)
 7 {
 8     GPIO_InitTypeDef GPIO_InitStructure;
 9
10     /*开启按键GPIO口的时钟*/
11     KEY1_GPIO_CLK_ENABLE();
12     KEY2_GPIO_CLK_ENABLE();
13     /*选择按键的引脚*/
14     GPIO_InitStructure.Pin = KEY1_PIN;
15
16     /*设置引脚为输入模式*/
17     GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
18
19     /*设置引脚不上拉也不下拉*/
20     GPIO_InitStructure.Pull = GPIO_NOPULL;
21
22     /*使用上面的结构体初始化按键*/
23     HAL_GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure);
24
25
26     /*选择按键的引脚*/
27     GPIO_InitStructure.Pin = KEY2_PIN;
28
29     /*使用上面的结构体初始化按键*/
30     HAL_GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure);
31
32 }

同为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 检测按键的状态

1 /** 按键按下标置宏
 2 * 按键按下为高电平,设置 KEY_ON=1, KEY_OFF=0
 3 * 若按键按下为低电平,把宏设置成KEY_ON=0 ,KEY_OFF=1 即可
 4 */
 5 #define KEY_ON  1
 6 #define KEY_OFF 0
 7
 8 /**
 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   */
16 uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
17 {
18     /*检测是否有按键按下 */
19     if (HAL_GPIO_ReadPin(GPIOx,GPIO_Pin) == KEY_ON ) {
20         /*等待按键释放 */
21         while (HAL_GPIO_ReadPin(GPIOx,GPIO_Pin) == KEY_ON);
22         return  KEY_ON;
23     } else
24         return KEY_OFF;
25 }

在这里我们定义了一个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 按键检测主函数

1 /**
 2   * @brief  主函数
 3   * @param  无
 4   * @retval 无
 5   */
 6 int main(void)
 7 {
 8     /* 系统时钟初始化成216 MHz */
 9     SystemClock_Config();
10     /* LED 端口初始化 */
11     LED_GPIO_Config();
12
13     /*初始化按键*/
14     Key_GPIO_Config();
15
16
17     /* 轮询按键状态,若按键按下则反转LED */
18     while (1) {
19         if ( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON  ) {
20             /*LED1反转*/
21             LED1_TOGGLE;
22         }
23
24         if ( Key_Scan(KEY2_GPIO_PORT,KEY2_PIN) == KEY_ON  ) {
25             /*LED2反转*/
26             LED2_TOGGLE;
27         }
28     }
29 }

代码中设置系统时钟为216MHz,初始化LED灯及按键后,在while函数里不断调用Key_Scan函数,并判断其返回值,若返回值表示按键按下,则反转LED灯的状态。

13.1.1  下载验证

把编译好的程序下载到开发板并复位,按下按键可以控制LED灯亮、灭状态。

原文地址:https://www.cnblogs.com/firege/p/9284145.html

时间: 2024-10-10 14:34:33

第13章 GPIO输入—按键检测的相关文章

第12章 GPIO输入-按键检测—零死角玩转STM32-F429系列

第12章 ????GPIO输入-按键检测 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege ? 本章参考资料:<STM32F4xx参考手册>.库帮助文档<stm32f4xx_dsp_stdperiph_lib_um.chm>. 按键检测使用到GPIO外设的基本输入功能,本章中不再赘述GPIO外设的概念,如您忘记了,可重读前面"GPIO框图剖析"小

第12章 GPIO输入—按键检测

第12章     GPIO输入-按键检测 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege 本章参考资料:<STM32F4xx参考手册>.库帮助文档<stm32f4xx_dsp_stdperiph_lib_um.chm>. 按键检测使用到GPIO外设的基本输入功能,本章中不再赘述GPIO外设的概念,如您忘记了,可重读前面"GPIO框图剖析"小节,

GPIO输入——按键检测

当按下一个按键时,系统是如何检测到的呢? 我们通过LED灯的亮灭状态来间接完成按键检测.当按下按键时,LED灯亮,再次按下时,LED灯灭. 要完成这个实验,我们就会用到GPIO外设的基本输入功能. 查阅开发板的按键原理图,如图3-1. 图3-1 图中的K1.K2即为按键.以K1为例,当未按下按键时,其PA0引脚处于接地状态,即低电平,按下按键时,引脚接到电源,输入状态为高电平.所以只要我们检测按键对应引脚(这里是PA0)的输入电平状态,即可判断按键是否被按下.这便是按键的检测原理了. 有一点需要

GPIO 输入—按键检测

这里要用到一定的模电知识.电容两端电压不能突变,电感两端电流不能突变.这里利用了电容的放电延时实现硬件消抖.按键按下会有抖动,波形有毛刺,使得高低电平显现不明显,而按键按下时,电容放电一下,马上又被充电,此时电容两端的电压不会突然变化,这个延时时间恰好可以达到消抖作用. 这里需要使用一个固件库函数: /** * @brief Reads the specified input port pin. * @param GPIOx: where x can be (A..K) to select th

第13章 GPIO—位带操作

第13章     GPIO-位带操作 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege 本章参考资料:<STM32F4xx 中文参考手册>存储器和总线构架章节.GPIO章节,<Cortex?-M4内核编程手册>2.2.5 Bit-banding.学习本章时,配套这些参考资料学习效果会更佳. 13.1 位带简介 位操作就是可以单独的对一个比特位读和写,这个在51单片机

【C语言学习】《C Primer Plus》第13章 文件输入/输出

学习总结 1.文件函数原型1: FILE* fopen(char *filename, char *openmode);  //打开文件,返回文件指针 filename:文件名,更确切地说,是包含文件名的字符串地址: openmode:打开模式(r,w,a,r+,w+,a+,……) 打开失败返回NULL int getc(FILE *fp);  //读文件,返回字符 fp:读取文件指针 int putc(int ch, FILE *fp);  //写文件,返回写入字符的ASCII值 ch:字符

第 13 章 文件输入/输出 (标准I/O)

1 /*-------------------------- 2 count.c -- 使用标准 I/O 3 --------------------------*/ 4 5 #include <stdio.h> 6 #include <stdlib.h> //提供 exit() 函数原型 7 8 int main(int argc, char *argv[]) 9 { 10 int ch; //读取文件时,储存每个字符的地方 11 FILE *fp; //文件指针 12 unsi

第13章 GPIO-位带操作—零死角玩转STM32-F429系列

第13章 ????GPIO-位带操作 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege ? 本章参考资料:<STM32F4xx 中文参考手册>存储器和总线构架章节.GPIO章节,<Cortex?-M4内核编程手册>2.2.5 Bit-banding.学习本章时,配套这些参考资料学习效果会更佳. 13.1 位带简介 位操作就是可以单独的对一个比特位读和写,这个在51单

第11章 GPIO输出-使用固件库点亮LED—零死角玩转STM32-F429系列

第11章 ????GPIO输出-使用固件库点亮LED 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege ? 本章参考资料:<STM32F4xx参考手册>.库帮助文档<stm32f4xx_dsp_stdperiph_lib_um.chm>. 利用库建立好的工程模板,就可以方便地使用STM32标准库编写应用程序了,可以说从这一章我们才开始迈入STM32开发的大门. LE