最近在群里跟小伙伴聊到按键键值的获取方式,提到一种使用状态机的方式,小伙伴有点疑问,小飞哥马上放下饭碗,停止干饭,撸他一个,大神自动飘过...不想飘过的,欢迎批评指导~
实验目标
- 学会HAL库定时器的配置及使用
- 状态机法获取键值
软件环境
- cubemx
- keil5
硬件环境
- 能“点灯”的板子
- 按键4个(我用的是正点原子系列的,4个按键)
- TFT LCD(可选)
一、cubemx配置
鉴于本次实验难度不高,也不宜多吹牛x,所以直接干就完事了!
Q&A 什么是状态机?
来源:https://blog.csdn.net/xinghuanmeiying/article/details/81586954
大家可以前去查看该博主,或者百度哈~
1.1 按键配置:
这是我的硬件连接,小伙伴们根据自己的配置进行,
1.2 定时器3配置
配置比较简单,就不啰嗦了,不懂的话,欢迎加群,轰炸我~
二、软件代码编写
2.1 定时器相关函数
代码语言:javascript复制void TIM3_Init(void)
{
HAL_TIM_Base_Start_IT(&htim3); //开启定时器中断3,10ms中断周期
}
/*
定时器中断回调函数
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM3) //定时器中断3发生中断事件
{
if (Key_Scan_TimCallBack())
{
key_value = Key_Scan_TimCallBack();
}
}
}
2.2 按键相关函数
代码语言:javascript复制
//下面的方式是通过直接操作HAL库函数方式读取IO
#define KEY0 HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) //KEY0按键PE4
#define KEY1 HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) //KEY1按键PE3
#define KEY2 HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) //KEY2按键PE2
#define WK_UP HAL_GPIO_ReadPin(WK_UP_GPIO_Port, WK_UP_Pin) //WKUP按键PA0
#define KEY0_PRES 1
#define KEY1_PRES 2
#define KEY2_PRES 3
#define WKUP_PRES 4
typedef enum
{
key_no_Press, //按键尚未按下
key_Press, //按键按下
key_PressCheck, //按键是否松开
key_Release //按键松开
}key_status;
/*----------------------------------------------------------------
按键IO状态查询函数
----------------------------------------------------------------*/
uint8_t KEY_Scan(void)
{
if ((KEY0 == 0 || KEY1 == 0 || KEY2 == 0 || WK_UP == 1))
{
if (KEY0 == 0)
return KEY0_PRES;
else if (KEY1 == 0)
return KEY1_PRES;
else if (KEY2 == 0)
return KEY2_PRES;
else if (WK_UP == 1)
return WKUP_PRES;
}
else if (KEY0 == 1 && KEY1 == 1 && KEY2 == 1 && WK_UP == 0)
return 0; //无按键按下
}
/*----------------------------------------------------------------
定时器中断中调用此函数
----------------------------------------------------------------*/
uint8_t Key_Scan_TimCallBack(void)
{
static key_status Press_status;
uint8_t key = 0;
switch (Press_status)
{
case key_no_Press:
if (KEY_Scan()) //有按键按下
{
Press_status ;
key = 0;
}
else
{
Press_status = key_no_Press;
key = 0;
}
break;
case key_Press:
if (KEY_Scan()) //有按键按下,第一次消抖,仍有按键按下,认为按键有效
{
Press_status ;
key = KEY_Scan();
}
break;
case key_PressCheck:
if (KEY_Scan()) //有按键按下,仍有按键按下,可做长按键判断,目前仍按照短按键键值处理,可修改
{
Press_status ;
key = KEY_Scan();
}
break;
case key_Release:
if (KEY_Scan()) //有按键按下,仍有按键按下,可做长按键判断,目前仍按照短按键键值处理,可修改
{
Press_status = key_no_Press;
key = 0;
}
break;
default:
Press_status = key_no_Press;
key = 0;
}
if (key)
{
key_debug_printf("key value is %drn", key);
}
return key;
}
2.3 LCD显示相关
本次的介绍就到这里啦,后面有更精彩的内容,欢迎大家持续关注嵌入式实验基地,来这里还可以学习HAL库 cubemx的更多精彩内容哦!