1)实验平台:正点原子STM32mini开发板
2)摘自《正点原子STM32 不完全手册(HAL 库版)关注官方微信号公众号,获取更多资料:正点原子

第七章 按键输入实验

上一章,我们介绍了 STM32 的 IO 口作为输出的使用,这一章,我们将向大家介绍如何使

用 STM32 的 IO 口作为输入用。在本章中,我们将利用板载的 3 个按键,来控制板载的两个 LED

的亮灭。通过本章的学习,你将了解到 STM32 的 IO 口作为输入口的使用方法。本章分为如下

几个小节:

7.1 STM32 IO 口简介

7.2 硬件设计

7.3 软件设计

7.4 下载验证

7.1 STM32 IO 口简介

STM32 的 IO 口在上一章已经有了详细的介绍,这里我们不再多说。STM32 的 IO 口做输

入使用的时候,是通过读取 IDR 的内容来读取 IO 口的状态的。了解了这点,就可以开始我们

的代码编写了。

这一节,我们将通过 MiniSTM32 开发板上载有的 3 个按钮(KEY0/KEY1/WK_UP),来控

制板上的 2 个 LED,其中 KEY0 控制 DS0,按一次亮,再按一次,就灭。KEY1 控制 DS1,效

果同 KEY0。WK_UP 按键则同时控制 DS0 和 DS1,按一次,他们的状态就翻转一次。

7.2 硬件设计

本实验用到的硬件资源有:

1) 指示灯 DS0、DS1

2) 3 个按键:KEY0、KEY1 和 KEY_UP。

DS0、DS1 和 STM32 的连接在上一章已经介绍了,在 MiniSTM32 开发板上的按键 KEY0

连接在 PC5 上、KEY1 连接在 PA15 上、WK_UP 连接在 PA0 上。如图 7.2.1 所示:

图 7.2.1 按键与 STM32 连接原理图

这里需要注意的是:KEY0 和 KEY1 是低电平有效的,而 WK_UP 是高电平有效的,除了

KEY1 有上拉电阻(与 JTDI 共用),其他两个都没有上下拉电阻,所以,需要在 STM32 内部设

置上下拉。

7.3 软件设计

这里的代码设计,我们还是在之前的基础上继续编写,打开上一章的 TEST 工程,然后在

HARDWARE 文件夹下新建一个 KEY 文件夹,用来存放与按键相关的代码。如图 7.3.1 所示:

图 7.3.1 在 HARDWARE 下新增 KEY 文件夹

然后我们打开 USER 文件夹下的 test.uvprojx 工程,按

按钮新建一个文件,然后保存在

HARDWARE→KEY 文件夹下面,保存为 key.c。在该文件中输入如下代码:

#include "key.h"

#include "delay.h"

//按键初始化函数

void KEY_Init(void)

{

GPIO_InitTypeDef GPIO_Initure;

__HAL_RCC_GPIOA_CLK_ENABLE(); //开启 GPIOA 时钟

__HAL_RCC_GPIOC_CLK_ENABLE(); //开启 GPIOC 时钟

GPIO_Initure.Pin=GPIO_PIN_0;

//PA0

GPIO_Initure.Mode=GPIO_MODE_INPUT; //输入

GPIO_Initure.Pull=GPIO_PULLDOWN; //下拉

GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH; //高速

HAL_GPIO_Init(GPIOA,&GPIO_Initure);

GPIO_Initure.Pin=GPIO_PIN_15;

//PA15

GPIO_Initure.Pull=GPIO_PULLUP; //上拉

HAL_GPIO_Init(GPIOA,&GPIO_Initure);

GPIO_Initure.Pin=GPIO_PIN_5;

//PC5

GPIO_Initure.Pull=GPIO_PULLUP; //上拉

HAL_GPIO_Init(GPIOC,&GPIO_Initure);

}

//按键处理函数

//返回按键值

//mode:0,不支持连续按;1,支持连续按;

//0,没有任何按键按下

//1,WKUP 按下 WK_UP

//注意此函数有响应优先级,KEY0>KEY1>KEY2>WK_UP!!

u8 KEY_Scan(u8 mode)

{

static u8 key_up=1; //按键松开标志

if(mode==1)key_up=1; //支持连按

if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))

{

delay_ms(10);

key_up=0;

if(KEY0==0) return KEY0_PRES;

else if(KEY1==0) return KEY1_PRES;

else if(WK_UP==1) return WKUP_PRES;

}else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1;

return 0; //无按键按下

}

这段代码包含 2 个函数,void KEY_Init(void)和 u8 KEY_Scan(u8 mode),KEY_Init 是用来

初始化按键输入的 IO 口的。实现 PA0、PA15 和 PC5 的输入设置,注意这调用了:JTAG_Set

这个函数,用于禁止 JTAG,开启 SWD,因为 PA15 占用了 JTAG 的一个 IO,所以要禁止 JTAG,

从而让 PA15 用作普通 IO 输入。

KEY_Scan 函数,则是用来扫描这 3 个 IO 口是否有按键按下。KEY_Scan 函数,支持两种

扫描方式,通过 mode 参数来设置。

当 mode 为 0 的时候,KEY_Scan 函数将不支持连续按,扫描某个按键,该按键按下之后必

须要松开,才能第二次触发,否则不会再响应这个按键,这样的好处就是可以防止按一次多次

触发,而坏处就是在需要长按的时候就不合适了。

当 mode 为 1 的时候,KEY_Scan 函数将支持连续按,如果某个按键一直按下,则会一直返

回这个按键的键值,这样可以方便的实现长按检测。

有了 mode 这个参数,大家就可以根据自己的需要,选择不同的方式。这里要提醒大家,

因为该函数里面有 static 变量,所以该函数不是一个可重入函数,在有 OS 的情况下,这个大家

要留意下。同时还有一点要注意的就是,该函数的按键扫描是有优先级的,最优先的是 KEY0,

第二优先的是 KEY1,最后是 WK_UP 按键。该函数有返回值,如果有按键按下,则返回非 0

值,如果没有或者按键不正确,则返回 0。

保存 key.c 代码,然后我们按同样的方法,新建一个 key.h 文件,也保存在 KEY 文件夹下

面。在 key.h 中输入如下代码:

#ifndef __KEY_H

#define __KEY_H

#include "sys.h"

#define KEY0 HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_5) //KEY0 按键 PC5

#define KEY1 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_15) //KEY1 按键 PA15

#define WK_UP HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) //WKUP 按键 PA0

#define KEY0_PRES 1

#define KEY1_PRES 2

#define WKUP_PRES 3

void KEY_Init(void);

u8 KEY_Scan(u8 mode);

#endif

这段代码里面最关键就是 3 个宏定义:

#define KEY0 HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_5) //KEY0 按键 PC5

#define KEY1 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_15) //KEY1 按键 PA15

#define WK_UP HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) //WKUP 按键 PA0

这里使用的是位带操作来实现读取某个 IO 口的 1 个位的。同输出一样,上面的功能也同

样可以通过位带操作来简单的实现:

#define KEY0 PCin(5) //KEY0 按键 PC5

#define KEY1 PAin(15) //KEY1 按键 PA15

#define WK_UP PAin(0) //WKUP 按键 PA0

用库函数实现的好处是在各个 STM32 芯片上面的移植性非常好,不需要修改任何代码。

用位带操作的好处是简洁,至于使用哪种方法,看各位的爱好了。

在 key.h 中,我们还定义了 KEY0_PRES / KEY1_PRES / KEYUP_PRES 等 3 个宏定义,分

别对应开发板的 KEY0、KEY1 和 WK_UP 按键按下时 KEY_Scan 的返回值。通过这些宏定义,

可以方便大家记忆和使用。

将 key.h 也保存一下。接着,我们把 key.c 加入到 HARDWARE 这个组里面,这一次我们通

过双击的方式来增加新的.c 文件,双击 HARDWARE,找到 key.c,加入到 HARDWARE 里面,

如图 7.3.2 所示:

图 7. 3.2 将 key.c 加入 HARDWARE 组下

可以看到 HARDWARE 文件夹里面多了一个 key.c 的文件, 然后还是用老办法把 key.h 头

文件所在的路径加入到工程里面。回到主界面,在 test.c 里面编写如下代码:

#include "sys.h"

#include "usart.h"

#include "delay.h"

#include "led.h"

#include "key.h"

int main(void)

{

u8 key=0;

HAL_Init();

//初始化 HAL 库

Stm32_Clock_Init(RCC_PLL_MUL9); //设置时钟,72M

delay_init(72);

//初始化延时函数

LED_Init();

//初始化 LED

KEY_Init();

//初始化按键

LED0=0;

//点亮 LED

while(1)

{

key=KEY_Scan(0);

//得到键值

switch(key)

{

case KEY0_PRES:

LED0=!LED0;

break;

case KEY1_PRES:

LED1=!LED1;

break;

case WKUP_PRES:

LED0=!LED0;

LED1=!LED1;

break;

default:

delay_ms(10);

}

}

}

注意要将 KEY 文件夹加入头文件包含路径,不能少,否则编译的时候会报错。这段代码

就实现前面 7.1 节所阐述的功能,相对比较简单。

然后按

,编译工程,得到结果如图 7.3.3 所示

图 7.3.3 编译结果

可以看到没有错误,也没有警告。接下来,大家就可以下载验证了。

7.4 下载验证

同样,我们还是通过 flymcu 下载代码,在下载完之后,我们可以按 KEY0、KEY1 和 KEY_UP

来看看 DS0 和 DS1 以及蜂鸣器的变化,是否和我们预期的结果一致?

特别注意:因为 PA0 用作按键输入,而且是高电平有效的,所以不要把 PA0 和 1820 的跳

线帽短接在一起了,否则会按键“失灵”。

至此,我们的本章的学习就结束了。本章,作为 STM32F1 的入门第三个例子,介绍了

STM32F1 的 IO 作为输入的使用方法,同时巩固了前面的学习。希望大家在开发板上实际验证

一下,从而加深印象。

stm32 工业按键检测_「正点原子STM32Mini板资料连载」第七章 按键输入实验相关推荐

  1. stm32 读取sd卡图片显示_「正点原子STM32Mini板资料连载」第三十五章 汉字显示实验...

    1)实验平台:正点原子STM32mini开发板 2)摘自<正点原子STM32 不完全手册(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第三十五章 汉字显示实验 汉字显示在 ...

  2. stm32l0的停止模式怎么唤醒_「正点原子STM32Mini板资料连载」第十九章 待机唤醒实验...

    1)实验平台:正点原子STM32mini开发板 2)摘自<正点原子STM32 不完全手册(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第十九章 待机唤醒实验 本章我们将向 ...

  3. 1709 ltsb 内存占用_「正点原子STM32Mini板资料连载」第三十二章 内存管理实验

    1)实验平台:正点原子STM32mini开发板 2)摘自<正点原子STM32 不完全手册(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第三十二章 内存管理实验 上一章,我 ...

  4. 看门狗寄存器c语言代码_「正点原子NANO STM32F103开发板资料连载」第十一章 看门狗实验...

    1)实验平台:[正点原子] NANO STM32F103 开发板 2)摘自<正点原子STM32 F1 开发指南(NANO 板-HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 ...

  5. 判断按键值_「正点原子NANO STM32开发板资料连载」第十六章电容触摸按键实验...

    1)实验平台:ALIENTEK NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第十六章电容 ...

  6. stm32 文件系统dma大小_「正点原子NANO STM32F103开发板资料连载」第二十二章 DMA 实验...

    1)实验平台:[正点原子] NANO STM32F103 开发板 2)摘自<正点原子STM32 F1 开发指南(NANO 板-HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 ...

  7. stm32看门狗_「正点原子NANO STM32开发板资料连载」第十一章 独立看门狗实验

    1)实验平台:ALIENTEK NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第十一章 独 ...

  8. 韦东山 IMX6ULL和正点原子_「正点原子NANO STM32开发板资料连载」第三章 MDK5 软件入门1...

    1)实验平台:ALIENTEK NANO STM32F411 V1开发板 2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第三章 M ...

  9. 嵌入式实时操作系统ucos-ii_「正点原子NANO STM32开发板资料连载」第三十八章 UCOSII 实验 3...

    1)实验平台:alientek NANO STM32F411 V1开发板2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第三十八章 ...

最新文章

  1. Ubuntu12.04 安装 mongodb
  2. 【错误记录】Flutter 构建报错 ( Because xxx requires SDK version >=2.12.0-0 <3.0.0, versio | Dart SDK 版本低 )
  3. 二分法(递归非递归)
  4. flink写入 mysql_flink写数据到mysql(java)
  5. WebService的学习
  6. git - 基础 - 01 - git reset --hard 回滚以后,看不到之前的分支版本怎么解决:
  7. go interface类型转换_Go语言的九大核心特性主要有哪些?
  8. beetle 2.7海量消息广播测试
  9. 面板x轴模式包括哪些_虎扑轻跃 | 体验一汽大众探岳X
  10. Git学习笔记 - 钢钢更新
  11. 数据结构之--series,DataFrame.use python and pandas for data mining
  12. java 面试 概率论_仿概率论系列(一) 开篇引导
  13. 高等数学——常用不定积分公式
  14. 谷歌Chrome浏览器就能远程控制安卓手机,电脑远程控制手机的快捷方法get!
  15. linux磁盘配额测试,Linux磁盘配额测试过程完全攻略
  16. Unity 灯光系统(一)
  17. 学习强国十年磨剑最新分数及排名
  18. 【CTR预估】The Wide and Deep Learning Model(译文+Tensorlfow源码解析)
  19. 桑基图绘制的简易操作
  20. 计算机网络的基本知识和技术

热门文章

  1. html5 文字定义线宽,html 5画布线宽
  2. python计算身体质量指数_利用Python计算身体质量指数BMI来判断体型
  3. 胡想——对机器人控制体系的一些想法
  4. key php 转小写_PHP代码层防护与绕过
  5. tensorflow创建张量
  6. python 下载大文件
  7. 目标定位--Deep Self-Taught Learning for Weakly Supervised Object Localization
  8. python协程异步原理_简单介绍Python的Tornado框架中的协程异步实现原理
  9. c语言bool怎么用_C语言中的一维数组和二维数组什么?怎么用?
  10. C++_类和结构体所占内存大小,静态成员问题