OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 778|回复: 0

《M144Z-M3最小系统板使用指南——STM32F103版》第十一章 按键输入实验

[复制链接]

1117

主题

1128

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4667
金钱
4667
注册时间
2019-5-8
在线时间
1224 小时
发表于 2024-3-27 16:20:58 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2024-3-26 12:02 编辑

第十一章 按键输入实验
1)实验平台:正点原子 M144Z-M3 STM32F103最小系统板

2) 章节摘自【正点原子】M144Z-M3最小系统板使用指南——STM32F103版

3)购买链接:https://detail.tmall.com/item.htm?&id=609293737870

4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boar ... _mini_sysboard.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)正点原子STM32技术交流QQ群:725095144

155537c2odj87vz1z9vj6l.jpg

155537nfqovl2gg9faaol9.png

上一章中介绍了GPIO的输出模式,并用其控制LED的亮灭。在实际的应用尝尽中,还会需要使用到GPIO的输入模式,来获取外部的输入信号,例如获取按键的状态。通过本章的学习,读者将学习到GPIO作为输入模式的使用。
本章分为如下几个小节:
11.1 硬件设计
11.2 程序设计
11.3 下载验证

11.1 硬件设计
11.1.1 例程功能
1. 按下WKUP按键,LED0状态翻转。
2. 按下KEY0按键,LED1状态翻转。

11.1.2 硬件资源
1. LED
       LED0 - PB5
       LED1 - PE5
2. 按键
       WKUP - PA0
       KEY0 - PE4

11.1.3 原理图
本章实验使用的两个M144Z-M3最小系统板STM32F103版板载按键,分别为KEY0按键和WKUP按键,其于板载MCU的连接原理图,如下图所示:                                
image001.png
图11.1.3.1 按键与MCU的连接原理图
从上面的原理图中可以看出,WKUP按键和KEY0按键的一端连接到了电源正极,而另一端分别与MCU的PA0引脚和PE4引脚相连接,因此当任意一个按键被按下时,MCU对应的引脚都能够读取到高电平的状态,而当松开按键后,MCU对应的引脚读取到的电平状态却是是确定的,因此用于读取WKUP按键和KEY0按键的PA0引脚和PE4引脚不仅要配置为输入模式,还需要配置成下拉,使对应引脚在悬空时被下拉在电源负极。

11.2 程序设计
11.2.1 HAL库的GPIO驱动
本章实验中要通过读取GPIO引脚的输入状态来判断按键是否被按下,以此来控制对应LED的状态翻转,因此对于判断按键的状态,需要以下几个步骤:
①:配置GPIO引脚为输入模式和下拉
②:读取GPIO引脚的输入状态
在HAL库中对应的驱动函数如下:
①:配置GPIO引脚
请见第10.2.1小节中配置GPIO引脚的相关内容。
②:读取GPIO引脚输入电平
该函数用于读取GPIO引脚的输入电平(高电平或低电平),其函数原型如下所示:
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
该函数的形参描述,如下表所示:
QQ截图20240326120202.png
表11.2.1.1 函数HAL_GPIO_ReadPin()形参描述
该函数的返回值描述,如下表所示:
QQ截图20240326120214.png
表11.2.1.2 函数HAL_GPIO_ReadPin()返回值描述
该函数的使用示例,如下所示:
  1. #include"stm32f1xx_hal.h"

  2. void example_fun(void)
  3. {
  4.     GPIO_PinState value;
  5.    
  6.     /* 读取PA0引脚输入电平 */
  7.     value = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
  8.    
  9.     if (value == GPIO_PIN_SET)
  10.     {
  11.          /* Do something.*/
  12.     }
  13.     else
  14.     {
  15.          /* Do something.*/
  16.     }
  17. }
复制代码

11.2.2按键驱动
按键驱动主要就是读取GPIO引脚的输入状态,以此判断按键是否被按下,本章实验中,按键的驱动代码包括key.c和key.h两个文件。
根据原理图可知,应当将PA0引脚和PA15引脚配置为输入模式和下拉,并在需要读取WKUP按键(KEY0按键)状态的时候,读取PA0引脚(PA15引脚)的输入电平,若读取到PA0引脚(PA15引脚)的输入电平为高电平,则说明WKUP按键(KEY0按键)被按下,反之,则说明WKUP按键(KEY0按键)没有被按下。
按键驱动中,对引脚的定义,如下所示:
  1. #define WKUP_GPIO_PORT         GPIOA
  2. #define WKUP_GPIO_PIN          GPIO_PIN_15
  3. #define WKUP_GPIO_CLK_ENABLE() do { __HAL_RCC_GPIOA_CLK_ENABLE(); } while (0)

  4. #define KEY0_GPIO_PORT         GPIOA
  5. #define KEY0_GPIO_PIN          GPIO_PIN_0
  6. #define KEY0_GPIO_CLK_ENABLE() do { __HAL_RCC_GPIOA_CLK_ENABLE(); } while (0)
复制代码
按键驱动中,操作引脚的定义,如下所示:
  1. #define WKUP (                                                              \
  2.    (HAL_GPIO_ReadPin(WKUP_GPIO_PORT, WKUP_GPIO_PIN) == GPIO_PIN_RESET) ?  \
  3.     0 :                                                                     \
  4.     1)
  5. #define KEY0 (                                                              \
  6.    (HAL_GPIO_ReadPin(KEY0_GPIO_PORT, KEY0_GPIO_PIN) == GPIO_PIN_RESET) ?  \
  7.     0 :                                                                     \
  8.     1)
复制代码
按键驱动中,按键的初始化函数,如下所示:
  1. /**
  2. *@brief   初始化按键
  3. *@param   无
  4. *@retval  无
  5. */
  6. void key_init(void)
  7. {
  8.    GPIO_InitTypeDef gpio_init_struct = {0};
  9.    
  10.     /* 使能GPIO端口时钟 */
  11.    WKUP_GPIO_CLK_ENABLE();
  12.    KEY0_GPIO_CLK_ENABLE();
  13.    
  14.     /* 配置WKUP控制引脚 */
  15.    gpio_init_struct.Pin = WKUP_GPIO_PIN;
  16.    gpio_init_struct.Mode = GPIO_MODE_INPUT;
  17.    gpio_init_struct.Pull = GPIO_PULLDOWN;
  18.    gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;
  19.    HAL_GPIO_Init(WKUP_GPIO_PORT, &gpio_init_struct);
  20.    
  21.     /* 配置KEY0控制引脚 */
  22.    gpio_init_struct.Pin = KEY0_GPIO_PIN;
  23.    gpio_init_struct.Mode = GPIO_MODE_INPUT;
  24.    gpio_init_struct.Pull = GPIO_PULLDOWN;
  25.    gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;
  26.    HAL_GPIO_Init(KEY0_GPIO_PORT, &gpio_init_struct);
  27. }
复制代码
按键的初始化函数中,使能了KEY0按键和WKUP按键对应引脚的GPIO端口时钟,并将其配置为输入模式和下拉。
按键的驱动中,扫描按键状态的函数,如下所示:
  1. /**
  2. *@brief   扫描按键
  3. *@note    按键响应具有优先级:WKUP > KEY0
  4. *@param   mode: 扫描模式
  5. *@arg     0: 不支持连续按
  6. *@arg     1: 支持连续按
  7. *@retval  按键键值
  8. *@arg     NONE_PRES: 没有按键按下
  9. *@arg     WKUP_PRES: WKUP按键按下
  10. *@arg     KEY0_PRES: KEY0按键按下
  11. */
  12. uint8_t key_scan(uint8_t mode)
  13. {
  14.     static uint8_t key_release = 1;
  15.     uint8_t key_value = NONE_PRES;
  16.    
  17.     if (mode != 0)
  18.     {
  19.          key_release = 1;
  20.     }
  21.    
  22.     if ((key_release == 1) && ((WKUP == 1) || (KEY0 == 1)))
  23.     {
  24.          delay_ms(10);
  25.          key_release = 0;
  26.          
  27.          if (KEY0 == 1)
  28.          {
  29.              key_value = KEY0_PRES;
  30.          }
  31.          
  32.          if (WKUP == 1)
  33.          {
  34.              key_value = WKUP_PRES;
  35.          }
  36.     }
  37.     else if ((WKUP == 0) && (KEY0 == 0))
  38.     {
  39.          key_release = 1;
  40.     }
  41.    
  42.     return key_value;
  43. }
复制代码
以上函代码就实现了按键扫描,且具有按键消抖的功能。

11.2.3 实验应用代码
本章实验的应用代码,如下所示:
  1. int main(void)
  2. {
  3.     uint8_t key;
  4.    
  5.    HAL_Init();                         /* 初始化HAL库 */
  6.    sys_stm32_clock_init(RCC_PLL_MUL9); /* 配置时钟,72MHz */
  7.    delay_init(72);                     /* 初始化延时 */
  8.    usart_init(115200);                 /* 初始化串口 */
  9.    led_init();                         /* 初始化LED */
  10.    key_init();                         /* 初始化按键 */
  11.    
  12.     while (1)
  13.     {
  14.          key = key_scan(0);             /* 扫描按键 */
  15.          
  16.          switch (key)
  17.          {
  18.              case WKUP_PRES:             /* WKUP按键被按下 */
  19.              {
  20.                  LED0_TOGGLE();          /* 翻转LED0状态 */
  21.                  break;
  22.              }
  23.              case KEY0_PRES:             /* KEY0按键被按下 */
  24.              {
  25.                      LED1_TOGGLE();      /* 翻转LED1状态 */
  26.                  break;
  27.              }
  28.          }
  29.          
  30.          delay_ms(10);
  31.     }
  32. }
复制代码
可以看到应用代码中,在初始化完LED和按键后,就进入了一个while循环,在循环中,每间隔10毫秒就调用key_scan()函数扫描以此按键的状态,如果扫描到KEY0按键或WKUP按键被按下,则反转对应LED的亮灭状态。

11.3 下载验证
在完成编译和烧录操作后,可以看到板子上的LED0和LED1默认是处于熄灭的状态,若此时按下并释放一次WKUP按键,则能够看到LED0的亮灭状态发生了一次翻转,同样的,若此时按下并释放一次KEY0按键,则能够看到LED1的亮灭状态发生了一次翻转,与预期的实验现象效果相符。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 05:54

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表