首先选择一个定时器 中断周期为10ms
1.Key.h中的内容
cnt_delay 为消抖次数 6*10ms 60ms的消抖时间 可以按照实际需求更改
后面长按按键可以根据需求 仿照写在time_read_key函数中
通过BIT5 在Key_GetNum函数中解析出数值
只写了长按和短按
连按之类的可以仿照继续写
把有关freertos的头文件和test任务删除就可以直接使用了
#ifndef _KEY_H
#define _KEY_H
#include "main.h"
#include "FreeRTOS.h"
#include "queue.h"
#define cnt_short_delay 6 //消抖数值 短按
#define cnt_long_delay 50 //消抖数值 长按
typedef enum //按键状态
{
BIT0=0, //初始状态
BIT1, //计数状态
BIT2, //短按状态确认
BIT3, //长按状态确认
}Key_Bit_t;
typedef struct {
GPIO_TypeDef *GPIOx; //端口号
uint16_t GPIO_PIN; //引脚号
int8_t cnt; //计数值
Key_Bit_t bit; //状态值
int key_value; //返回值
int8_t key_short_value; //短按值
int8_t key_long_value; //长按值
} KeyState_t;
extern KeyState_t Key_board;
extern int value_KEY;
extern QueueHandle_t g_xQueueKey;
void time_read_key(KeyState_t *key_state);//定时器读取按键
void Key_Test(void *argument);
#endif
2.Key.c
声明对象Key_board
#include "stm32f4xx_hal.h"
#include "key.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
KeyState_t Key_board = {
.GPIOx = KEY_GPIO_Port,
.GPIO_PIN = KEY_Pin,
.cnt = 0,
.bit = BIT0,
.key_value=0,
.key_short_value = 1,
.key_long_value = 2,
};
#if 0
static uint8_t Key_Init(void)
{
//This section is generated by Cube
return 0;
}
#endif
//定时器读取按键
void time_read_key(KeyState_t *key_state)
{
if (HAL_GPIO_ReadPin(key_state->GPIOx, key_state->GPIO_PIN) == RESET && key_state->bit==BIT0)
{
key_state->cnt=0;
key_state->bit = BIT1;
}
if(key_state->bit == BIT1)
{
key_state->cnt++;
if(HAL_GPIO_ReadPin(key_state->GPIOx, key_state->GPIO_PIN) == SET )
{
if(key_state->cnt >= cnt_short_delay&&key_state->cnt < cnt_long_delay)
{
key_state->bit = BIT2;
}
else if(key_state->cnt >= cnt_long_delay)
{
key_state->bit = BIT3;
}
else
key_state->bit = BIT0;
key_state->cnt = 0;
}
}
}
//获取键值
static int Key_GetNum(KeyState_t *key_state)
{
if(key_state->bit==BIT2)
{
key_state->bit=BIT0;
key_state->key_value=key_state->key_short_value;
return key_state->key_value;
}
if(key_state->bit==BIT3)
{
key_state->bit=BIT0;
key_state->key_value=key_state->key_long_value;
return key_state->key_value;
}
return 0;
}
int Key_Return_Num(void)
{
if(Key_GetNum(&Key_board)!=0)
{
return Key_board.key_value;
}
return 0;
}
int value_KEY=0;
QueueHandle_t g_xQueueKey; /* 按键队列 */
void Key_Test(void *argument)
{
while (1)
{
if(g_xQueueKey!=NULL) //创建队列成功
{
int keyValue = Key_Return_Num();
if (keyValue != 0)
{
value_KEY = keyValue;
xQueueSendToBack(g_xQueueKey, &value_KEY, pdMS_TO_TICKS(50));
}
}
vTaskDelay(10);
}
}
3.定时器调用