单片机
返回首页

【STM32单片机学习】第12章 GPIO—按键轮询

2025-11-07 来源:bilibili

12.1 关于按键

前面控制LED灯是让GPIO输出高低电平,而获取按键则是读取GPIO电平,从而获知用户是否按下按键。

按键监测一般有两种:按键扫描和按键中断。按键扫描是间隔很短时间反复查询GPIO状态,从而得知是否有按键动作,这种方式代码简单,但比较耗资源。按键中断而是通过按键产生中断信号,从而实现按键的检测,这种方式需要使用到中断机制,需要对MCU了解深入一点,效果是最好的。

本节先介绍按键扫描,理解按键的基本原理,下一章再介绍按键中断,同时了解STM32F103的中断使用方法。

按键一般占用一个GPIO口,通过监测该GPIO的电平变化得知按键操作,典型的电路如图 12.1.1 所示。当所需按键比较多时,则可以采用矩阵按键减少GPIO的占用。矩阵按键需要通过编程扫描等方式实现对多个按键的监控,这里以最简单的独立按键为基础进行介绍。

图 12.1.1 按键与MCU的连接方式示意图

可以看到,在没有按下按键时,电源3.3V通过电阻连接到MCU的PA0脚上,此时MCU读取PA0的电平就是3.3V的高电平。在按键按下时,电源3.3V经过电阻,再经过按键连接到了地,此时PA0连接到接地的一端,读到的电平就是0V的低电平。由此,MCU就可用过读取对应引脚的电平值,得知按键的变化。

常用的按键都是机械触点式按键,机械式按键在按下或释放的过程中,由于机械弹性作用的影响,会伴随机械抖动,如图 12.1.2 所示。

图 12.1.2 机械按键抖动示意图

抖动的时长与机械开关特性相关,一般为5-10ms。在这抖动过程中,会产生多次高低电平,导致被识别为多次按键操作。为了避免机械触点按键检测误判,必须消抖处理。按键消抖可以硬件上处理,即在按键旁并联电容,吸收抖动的电平。也可以软件处理,即通过延时,避开抖动。

由此,首先获取对应引脚的电平得知按键状态,再硬件或软件消除抖动。

12.2 硬件设计

开发板上有两个按键,一个是复位按键(K1,红色),另一个是用户按键(K2,白色),这里只有用户按键能够编程控制。

如图 12.2.1 为开发板用户按键部分的原理图,电容C15用于硬件去抖,可以看作不存在。按键松开时,3V3经过上拉电阻R20到网络标号KEY,网络标号KEY另一端连接MCU的PA0,此时读取PA0电平为高电平;按键按下时,3V3经过上拉电阻R20,再通过按键接地,此时读取PA0电平为低电平。

由此可知,按键按下,GPIO引脚电平变低,反之为高,按键所接GPIO为PA0。

图 12.2.1 用户按键原理图

12.3 软件设计

1.3.1 软件设计思路

实验目的:本实验通过轮询读方式取GPIO的输入电平判断按键是否按下,并操作LED。

1) 按键初始化:GPIO端口时钟使能、GPIO引脚设置为输入(PA0);

2) 封装每个按键处理函数:读取按键GPIO状态,操作LED灯亮灭;

3) 主函数轮询按键状态:一直检测是否有按键被按下;

本实验配套代码位于“5_程序源码5_GPIO—按键轮询”。

 

1.3.2 软件设计讲解

1) GPIO宏定义与接口宏定义

代码段 12.3.1 引脚宏定义(driver_key.h)

/*********************


 * 按键引脚状态定义


**********************/


#define PUSH_DOWN                       GPIO_PIN_RESET


#define SPRING_UP                       GPIO_PIN_SET




/*********************


 * 引脚宏定义


**********************/


#define KEY_GPIO_PIN                 GPIO_PIN_0


#define KEY_GPIO_PORT                GPIOA


#define KEY_GPIO_CLK_EN()            __HAL_RCC_GPIOA_CLK_ENABLE()




/*********************


 * 函数宏定义


**********************/


/*


 * 按键状态读取函数宏定义


*/


#define KEY                  HAL_GPIO_ReadPin(KEY_GPIO_PORT, KEY_GPIO_PIN)



根据硬件设计选定的对应按键的引脚,将其宏定义命名为KEY,且对他们的读取函数进行重命名。其中“HAL_GPIO_ReadPin()”原型“GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)”,参数依次是:引脚组,引脚号,返回的是0(低电平)或1(高电平)。


 


2) GPIO初始化


代码段 12.3.2 按键初始化(driver_key.c)


/*


 *  函数名:void KeyInit(void)


 *  输入参数:无


 *  输出参数:无


 *  返回值:无


 *  函数作用:初始化按键的引脚,配置为输入


*/


void KeyInit(void)


{


    // 定义GPIO的结构体变量


    GPIO_InitTypeDef GPIO_InitStruct = {0};


    // 使能按键的GPIO对应的时钟


    KEY_GPIO_CLK_EN();




    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;             // 设置为输入模式


    GPIO_InitStruct.Pull = GPIO_PULLUP;                 // 默认上拉


    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;       // 引脚反转速度设置为快




    // 初始化按键引脚配置


    GPIO_InitStruct.Pin = KEY_GPIO_PIN;              // 选择按键的引脚


    HAL_GPIO_Init(KEY_GPIO_PORT, &GPIO_InitStruct);


}

使能时钟,将引脚初始化为上拉输入。


 


3) 按键读取函数


为了展示效果,编写代码查询按键是否按下,按下后切换LED灯亮灭状态。


 代码段 12.3.3 按键读取函数(driver_key.c)


/*


*  函数名:void KeyPolling(void)


 *  输入参数:无


 *  输出参数:无


 *  返回值:无


 *  函数作用:使用轮询方式查询按键是否按下,通过按下控制LED灯亮灭


*/


static bool key_flag = false;


void KeyPolling(void)


{


    if(KEY == PUSH_DOWN)          // 如果检测到按键被按下


    {


        HAL_Delay(8);             // 延时8ms防按键抖动


        if(KEY == PUSH_DOWN)      // 如果防抖动后按键依然是处于被按下的状态,就认为按键被按下过


        {


            key_flag = !key_flag; // 用一个标志位来判断按键被按下次数,按下一次灯亮,再按一次灯灭,如此反复


BLED(key_flag?OFF:ON);


        }


    }


}

8行:定义了一个全局变量标志位“key_flag”,作为按键被按下的标志;


11行:获取该按键状态;


13行:延时5-10ms,软件去抖;


14行:再次获取该按键状态,此时依旧按下,说明是正常按键操作,非抖动;


16行:将标志位置反,按键按一次置反一次(即0->1->0->1这样循环);


17行:根据标志位“key_flag”的值,让LED灯亮或灭;


此时每按下一次按键键,蓝色LED灯将亮灭交替。


 


4) 主函数测试


代码段 12.3.4 主函数控制逻辑(main.c)


// 初始化LED


LedGpioInit();


// 初始化按键


KeyInit();




while(1)


{


    // 轮询按键键


    KeyPolling();


 }

1~4行:初始化LED灯和按键;


6~10行:一直循环查询每个按键当前状态,从而判断对应按键是否按下;


12.4 实验效果

本实验对应配套资料的“5_程序源码5_GPIO—按键轮询”。打开工程后,编译,下载。按下按键,用户LED灯亮/灭。

进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦线性调频增强器

  • 家用电器遥控器

  • 12V 转 28V DC-DC 变换器(基于 LM2585)

  • 红外开关

  • DS1669数字电位器

  • HA1377 桥式放大器 BCL 电容 17W(汽车音频)

    相关电子头条文章