STM32固件库实现按键控制

文章目录

  • 前言
  • 一、原理图
  • 二、软件设计
  • 三、代码
    • 1.按键引脚宏定义
    • 2. 按键 GPIO 初始化函数
    • 3. 检测按键的状态
    • 4. 主函数
  • 四、下载验证
  • 五、收获
    • 1.程序如何换行
    • 2.异或^


前言

使用固件库实现按键控制LED


提示:以下是本篇文章正文内容

一、原理图

STM32固件库实现按键控制_第1张图片
从按键的原理图可知,这些按键在没有被按下的时候,GPIO 引脚的输入状态为低电平(按键所在的电路不通,引脚接地),当按键按下时,GPIO 引脚的输入状态为高电平(按键所在的电路导通,引脚接到电源)。只要我们检测引脚的输入电平,即可判断按键是否被按下。

电容的作用:利用电容充放电的延时,消除了波纹,起到消抖功能。

二、软件设计

在“工程”上新建“bsp_key.c”及“bsp_key.h”文件,这些文件不属于STM32 标准库的内容,是由我们自己根据应用需要编写的,编程步骤如下:

  1. 使能 GPIO 端口时钟;
  2. 初始化 GPIO 目标引脚为输入模式(浮空输入);
  3. 编写简单测试程序,检测按键的状态,实现按键控制 LED 灯。

三、代码

1.按键引脚宏定义

在编写应用程序的过程中,要考虑更改硬件环境的情况,即提高可移植性。
这个时候一般把硬件相关的部分使用宏来封装,若更改了硬件环境,只修改这些硬件相关的宏即可,这
些定义一般存储在头文件,即本例子中的bsp_key.h文件中
代码如下:

1 // 引脚定义
2 #define KEY1_GPIO_CLK RCC_APB2Periph_GPIOA
3 #define KEY1_GPIO_PORT GPIOA
4 #define KEY1_GPIO_PIN GPIO_Pin_0
5
6 #define KEY2_GPIO_CLK RCC_APB2Periph_GPIOC
7 #define KEY2_GPIO_PORT GPIOC
8 #define KEY2_GPIO_PIN GPIO_Pin_13

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

2. 按键 GPIO 初始化函数

利用上面的宏,编写按键的初始化函数

1 void Key_GPIO_Config(void)
2 {
     
3 GPIO_InitTypeDef GPIO_InitStructure;
4
5 /*开启按键端口的时钟*/
6 RCC_APB2PeriphClockCmd(KEY1_GPIO_CLK|KEY2_GPIO_CLK,ENABLE);
7
8 //选择按键的引脚
9 GPIO_InitStructure.GPIO_Pin = KEY1_GPIO_PIN;
10 // 设置按键的引脚为浮空输入
11 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
12 //使用结构体初始化按键
13 GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
14
15 //选择按键的引脚
16 GPIO_InitStructure.GPIO_Pin = KEY2_GPIO_PIN;
17 //设置按键的引脚为浮空输入
18 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
19 //使用结构体初始化按键
20 GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure);
21 }

函数执行流程如下:
(1) 使用 GPIO_InitTypeDef 定义 GPIO 初始化结构体变量,以便下面用于存储 GPIO 配置。
(2) 调用库函数 RCC_APB2PeriphClockCmd 来使能按键的 GPIO 端口时钟。
(3) 向 GPIO 初始化结构体赋值,把引脚初始化成浮空输入模式。
(4) 使用以上初始化结构体的配置,调用 GPIO_Init 函数向寄存器写入参数,完成 GPIO 的初始化。
(5) 使用同样的初始化结构体,只修改控制的引脚和端口,初始化其它按键检测时使用的GPIO 引脚。

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...G)
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 (GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON ) {
     
20 /*等待按键释放 */
21 while (GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON);
22 return KEY_ON;
23 } else
24 return KEY_OFF;
25 }

在这里我们定义了一个 Key_Scan 函数用于扫描按键状态。GPIO 引脚的输入电平可通过 读 取 IDR 寄存器对应的数据位来感知。
STM32 标准库提供了库函数GPIO_ReadInputDataBit 来获取位状态,该函数输入 GPIO 端口及引脚号,函数返回该引脚的电平状态,高电平返回 1,低电平返回 0。
Key_Scan 函数中以 GPIO_ReadInputDataBit 的返回值与自定义的宏“KEY_ON”对比,若检测到按键按下,则使用 while 循环持续检测按键状态,直到按键释放,按键释放后 Key_Scan 函数返回一个“KEY_ON”值;若没有检测到按键按下,则函数直接返回“KEY_OFF”。

4. 主函数

接下来我们使用主函数编写按键检测流程

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

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

四、下载验证

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

五、收获

1.程序如何换行

代码中的“\”是 C 语言中的续行符语法,表示续行符的下一行与续行符所在的代码是同一行。代码中因为宏定义关键字“#define”只是对当前行有效,所以我们使用续行符来连接起来,应用续行符的时候要注意,在“\”后面不能有任何字符(包括注释、空格),只能直接回车。
应用:#define LED_G(a) if(a)
GPIO_RestBits(LED_G_GPIO_PORT,LED_G_GPIO_PIN);
else GPIO_SetBits(LED_G_GPIO_PORT,LED_G_GPIO_PIN);
使用续行就达到了宏定义是一行分成几行写的作用。

2.异或^

^异或 ,C语言中二进制运算符
功能:与1 异或改变,与0异或不变
应用:
GPIOB->ODR ^= GPIO_Pin_0;
ODR的第一位和1相异或,做到改变状态,输出高低电平的效果。

你可能感兴趣的:(STM32,stm32,keil,mdk)