配置CubeMX
代码部分
key.h
#include "stm32g4xx_hal.h"
#define Press(x) (HAL_GPIO_ReadPin(x))
#define KB4 GPIOA, GPIO_PIN_0
#define KB1 GPIOB, GPIO_PIN_0
#define KB2 GPIOB, GPIO_PIN_1
#define KB3 GPIOB, GPIO_PIN_2
//可修改
#define SHORT_DELAY 2 // 短按延时
#define LONG_DELAY 80 // 长按延时
#define CONTINUE_DELAY 10 // 连续触发延时
typedef struct {
uint8_t scan_flag; //按键定时扫描标识
uint16_t last_key; //上次按键值
uint8_t pressed; //按键是否已按下标识
uint16_t cnt; //按键按下时间长短计时器
}KeyScan_t;
uint8_t Key_Scan(void);
key.c
#include "key.h"
// 检测哪个按键按下
uint8_t Key_Scan(void){
if(Press(KB1) == 0){
return 1;
}
else if(Press(KB2) == 0){
return 2;
}
else if(Press(KB3) == 0){
return 3;
}
else if(Press(KB4) == 0){
return 4;
}
return 0;
}
判断是长按还是短按
//判断是长按还是短按
//定义变量
KeyScan_t key = {0,0,0,0};
int Key_1ms = 0;
void Key_Proc(void)
{
if(key.scan_flag == 1){
key.scan_flag = 0;
uint8_t cur_key = Key_Scan(); // 获取当前按键值
uint8_t key_down = cur_key & (cur_key ^ key.last_key); // 检测下降沿,只有第一次按键按下时不等于0
uint8_t key_up = ~cur_key & (cur_key ^ key.last_key); // 检测上升沿,必须先有按键按下,再释放时不等于0
if(key_down != 0){ // 按键按下时触发
key.pressed = 1; // 按下标识置1
key.cnt = 0; // 计时清0
}
if(key_up != 0){ // 按键释放时触发
key.pressed = 0;
}
if(key.pressed == 1){ // 按键处于按下状态
key.cnt++;
if(key.cnt == LONG_DELAY){ // 长按
switch(cur_key){
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
default:
break;
}
}else if(key.cnt >= LONG_DELAY+CONTINUE_DELAY){ // 持续长按
switch(cur_key){
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
default:
break;
}
}
}else {
if(key.last_key != 0 && key.cnt >= SHORT_DELAY && key.cnt < LONG_DELAY){ //短按
switch(key.last_key){ // 由于这次按键已经抬起,键值为NOKEY,所以只有判断上次的键值
case 1:
Show_Flag++;
if(Show_Flag == 3)
Show_Flag = 1;
break;
case 2:
if(Show_Flag == 2)
{
CNBR_Price += 0.5f;
VNBR_Price += 0.5f;
}
break;
case 3:
if(Show_Flag == 2)
{
CNBR_Price -= 0.5f;
VNBR_Price -= 0.5f;
if(CNBR_Price < 0)
CNBR_Price = 0.0f;
if(VNBR_Price < 0)
VNBR_Price = 0.0f;
}
break;
case 4:
break;
default:
;
}
}
}
key.last_key = cur_key;
}
}
使用定时器需添加两个函数
初始化函数
HAL_TIM_Base_Start_IT(&htim2);
回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
if(htim->Instance == TIM2){
Key_1ms++;
if(Key_1ms == 20){
key.scan_flag = 1;
Key_1ms = 0;
}
}
}