按键扫描模块化程序
根据proteus电路图我们可以找到按键的相关引脚;我们在stm32cube中配置时钟以及其他配置和LED灯一样;因为本节只是引入模块化,大部分在keil5中进行代码的编写;(单片机中也有详细的模块化教学)。😊
添加相关文件
众所周知所谓模块化编程就是让主函数中代码变得简练;把相关的功能分成不同模块;然后在主函数调用!
.c
.h
在这里我们不详细介绍编写.c,.h文件需要的格式;我们重点解释如何书写按键扫描功能的实现;
配置引脚
我们在电路图观察到相关引脚,在stm32cube配置生成代码;我们需要引入一些函数以及自变量来完成代码任务的实现;具体我们会在代码中纤细解释:
首先来编写.H文件
#ifndef __KEYSCAN_H // 定义的函数名字
#define __KEYSCAN_H
#include "stm32f4xx_hal.h"
//宏定义按键引脚
#define B1 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)
#define B2 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)
#define B3 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)
#define B4 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)
// 按键状态枚举
typedef enum // C语言将会介绍
{
KEY_UP=0, // 实现按键消抖;按键的三种状态:未按下,按下,等待松手;
KEY_DE,
KEY_WAIT
}KEY_STATE;
// 外部变量声明
extern uint8_t KEY_Value; // 定义按下按键哪个后返回哪个对应的数值
extern KEY_STATE KEYState; //按键的状态
extern volatile uint8_t KeyFlag; //是否有按键按下
// 按键扫描函数声明
void KeyScan(void);
#endif // KEYSAN_H
现在我们开始书写今天的“头号才艺” .c文件

主要思路是如果按键被按下,返回按键对应的数值,从而完成不同的按键按下实现不同的功能。
#include "KeyScan.h"
// 初始化按键状态
uint8_t KEY_Value = 0; // 这里就是默认数值为0;
KEY_STATE KEYState = KEY_UP;
volatile uint8_t KeyFlag = 0;
// 按键扫描函数实现
void KeyScan(void)
{
switch(KEYState)
{
case KEY_UP:
{
if((B1==GPIO_PIN_RESET)||(B2==GPIO_PIN_RESET)||(B3==GPIO_PIN_RESET)||(B4==GPIO_PIN_RESET))
// 这句话的意思是如果有一个按键被按下,||或的意思 按键按下为低电平
{
KEYState = KEY_DE;
}
}
case KEY_DE:
{
if((B1==GPIO_PIN_RESET)||(B2==GPIO_PIN_RESET)||(B3==GPIO_PIN_RESET)||(B4==GPIO_PIN_RESET))
{
KEYState = KEY_WAIT;
if(B1==GPIO_PIN_RESET) KEY_Value = 1;
if(B2==GPIO_PIN_RESET) KEY_Value = 2;
if(B3==GPIO_PIN_RESET) KEY_Value = 3;
if(B4==GPIO_PIN_RESET) KEY_Value = 4;
}
else KEYState = KEY_UP; break;
}
case KEY_WAIT:
{
if((B1==GPIO_PIN_RESET)||(B2==GPIO_PIN_RESET)||(B3==GPIO_PIN_RESET)||(B4==GPIO_PIN_RESET))
{
KEYState = KEY_UP;
KeyFlag = 1;
break;
}
}
}
}
上面的代码引入几个新的关于嵌入式函数和c语言中的关键词;我们在这里进行一下解释:
| 函数名 | 函数解释 |
|---|---|
| HAL_GPIO_ReadPin() | 读取一个引脚的电平 |
| typedef | 通过赋予类型更直观的名称 |
| switch | 一种多分支选择结构 |
写完文件之后我们要注意把文件放到项目放置.c,.h文件的地方;不然可能引起错误;在.h文件中写完后记得空一行;编写代码标准;
如果有不理解的地方
997

被折叠的 条评论
为什么被折叠?



