本程序结合安富莱以及正点原子写了一个适合自用的key程序
目前修改了freertos部分
参考代码如下
main.c
/*FreeRTOS配置*/
/* START_TASK 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define START_TASK_PRIO 1 /* 任务优先级 */
#define START_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t StartTask_Handler; /* 任务句柄 */
void start_task(void *pvParameters); /* 任务函数 */
/* TASK1 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK1_PRIO 2 /* 任务优先级 */
#define TASK1_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task1Task_Handler; /* 任务句柄 */
void task1(void *pvParameters); /* 任务函数 */
/* TASK2 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK2_PRIO 2 /* 任务优先级 */
#define TASK2_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task2Task_Handler; /* 任务句柄 */
void task2(void *pvParameters); /* 任务函数 */
/* TASK3 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK3_PRIO 3 /* 任务优先级 */
#define TASK3_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task3Task_Handler; /* 任务句柄 */
void task3(void *pvParameters); /* 任务函数 */
/******************************************************************************************************/
/* LCD刷屏时使用的颜色 */
uint16_t lcd_discolor[11] = {WHITE, BLACK, BLUE, RED,
MAGENTA, GREEN, CYAN, YELLOW,
BROWN, BRRED, GRAY};
/**
* @brief FreeRTOS例程入口函数
* @param 无
* @retval 无
*/
void freertos_demo(void)
{
xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */
(const char* )"start_task", /* 任务名称 */
(uint16_t )START_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */
vTaskStartScheduler();
}
/**
* @brief start_task
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
/* 创建任务2 */
xTaskCreate((TaskFunction_t )task2,
(const char* )"task2",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
/* 创建任务3 */
xTaskCreate((TaskFunction_t )task3,
(const char* )"task3",
(uint16_t )TASK3_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK3_PRIO,
(TaskHandle_t* )&Task3Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
/**
* @brief task1
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task1(void *pvParameters)
{
//uint32_t task1_num = 0;
while(1)
{
LED0_TOGGLE(); /* LED0闪烁 */
vTaskDelay(1000); /* 延时1000ticks */
}
}
/**
* @brief task2
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task2(void *pvParameters)
{
while(1)
{
/* 按键扫描 */
bsp_KeyScan();
vTaskDelay(10);
}
}
void task3(void *pvParameters)
{
uint8_t ucKeyCode;
while(1)
{
ucKeyCode = bsp_GetKey();
if (ucKeyCode != KEY_NONE)
{
switch (ucKeyCode)
{
/* K1键按下,直接发送事件标志给任务vTaskTCPnet,设置bit0 */
case KEY_DOWN_K1:
vTaskDelete(Task1Task_Handler); /* 删除开始任务 */
break;
/* 其他的键值不处理 */
default:
break;
}
}
vTaskDelay(20);
}
}
key.c
#include "./BSP/KEY/key.h"
static KEY_T s_tBtn[KEY_COUNT];
static KEY_FIFO_T s_tKey; /* 按键FIFO变量,结构体 */
static void bsp_InitKeyVar(void);
static void bsp_InitKeyHard(void);
static void bsp_DetectKey(uint8_t i);
/*如果按键触发电平不同请修改下方(if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) == 1)此处为高电平触发按键,
若低电平默认保持为0即可*/
static uint8_t IsKeyDown1(void) {if ((GPIO_PORT_K1->IDR & GPIO_PIN_K1) == 1) return 1;else return 0;}
static uint8_t IsKeyDown2(void) {if ((GPIO_PORT_K2->IDR & GPIO_PIN_K2) == 0) return 1;else return 0;}
static uint8_t IsKeyDown3(void) {if ((GPIO_PORT_K3->IDR & GPIO_PIN_K3) == 0) return 1;else return 0;}
static uint8_t IsKeyDown4(void) {if ((GPIO_PORT_K4->IDR & GPIO_PIN_K4) == 0) return 1;else return 0;}
/*static uint8_t IsKeyDown5(void) {if ((GPIO_PORT_K5->IDR & GPIO_PIN_K5) == 0) return 1;else return 0;}
static uint8_t IsKeyDown6(void) {if ((GPIO_PORT_K6->IDR & GPIO_PIN_K6) == 0) return 1;else return 0;}
static uint8_t IsKeyDown7(void) {if ((GPIO_PORT_K7->IDR & GPIO_PIN_K7) == 0) return 1;else return 0;}
static uint8_t IsKeyDown8(void) {if ((GPIO_PORT_K8->IDR & GPIO_PIN_K8) == 0) return 1;else return 0;}
static uint8_t IsKeyDown9(void) {if (IsKeyDown1() && IsKeyDown2()) return 1;else return 0;}
static uint8_t IsKeyDown10(void) {if (IsKeyDown1() && IsKeyDown2()) return 1;else return 0;}*/
/*
*********************************************************************************************************
* 函 数 名: bsp_InitKey
* 功能说明: 初始化按键. 该函数被 bsp_Init() 调用。
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitKey(void)
{
bsp_InitKeyVar(); /* 初始化按键变量 */
bsp_InitKeyHard(); /* 初始化按键硬件 */
}
/*
*********************************************************************************************************
* 函 数 名: bsp_PutKey
* 功能说明: 将1个键值压入按键FIFO缓冲区。可用于模拟一个按键。
* 形 参: _KeyCode : 按键代码
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_PutKey(uint8_t _KeyCode)
{
s_tKey.Buf[s_tKey.Write] = _KeyCode;
if (++s_tKey.Write >= KEY_FIFO_SIZE)
{
s_tKey.Write = 0;
}
}
/*
*********************************************************************************************************
* 函 数 名: bsp_GetKey
* 功能说明: 从按键FIFO缓冲区读取一个键值。
* 形 参: 无
* 返 回 值: 按键代码
*********************************************************************************************************
*/
uint8_t bsp_GetKey(void)
{
uint8_t ret;
if (s_tKey.Read == s_tKey.Write)
{
return KEY_NONE;
}
else
{
ret = s_tKey.Buf[s_tKey.Read];
if (++s_tKey.Read >= KEY_FIFO_SIZE)
{
s_tKey.Read = 0;
}
return ret;
}
}
/*
*********************************************************************************************************
* 函 数 名: bsp_GetKey2
* 功能说明: 从按键FIFO缓冲区读取一个键值。独立的读指针。
* 形 参: 无
* 返 回 值: 按键代码
*********************************************************************************************************
*/
uint8_t bsp_GetKey2(void)
{
uint8_t ret;
if (s_tKey.Read2 == s_tKey.Write)
{
return KEY_NONE;
}
else
{
ret = s_tKey.Buf[s_tKey.Read2];
if (++s_tKey.Read2 >= KEY_FIFO_SIZE)
{
s_tKey.Read2 = 0;
}
return ret;
}
}
/*
*********************************************************************************************************
* 函 数 名: bsp_GetKeyState
* 功能说明: 读取按键的状态
* 形 参: _ucKeyID : 按键ID,从0开始
* 返 回 值: 1 表示按下, 0 表示未按下
*********************************************************************************************************
*/
uint8_t bsp_GetKeyState(KEY_ID_E _ucKeyID)
{
return s_tBtn[_ucKeyID].State;
}
/*
*********************************************************************************************************
* 函 数 名: bsp_SetKeyParam
* 功能说明: 设置按键参数
* 形 参:_ucKeyID : 按键ID,从0开始
* _LongTime : 长按事件时间
* _RepeatSpeed : 连发速度
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_SetKeyParam(uint8_t _ucKeyID, uint16_t _LongTime, uint8_t _RepeatSpeed)
{
s_tBtn[_ucKeyID].LongTime = _LongTime; /* 长按时间 0 表示不检测长按键事件 */
s_tBtn[_ucKeyID].RepeatSpeed = _RepeatSpeed; /* 按键连发的速度,0表示不支持连发 */
s_tBtn[_ucKeyID].RepeatCount = 0; /* 连发计数器 */
}
/*
*********************************************************************************************************
* 函 数 名: bsp_ClearKey
* 功能说明: 清空按键FIFO缓冲区
* 形 参:无
* 返 回 值: 按键代码
*********************************************************************************************************
*/
void bsp_ClearKey(void)
{
s_tKey.Read = s_tKey.Write;
}
/*
*********************************************************************************************************
* 函 数 名: bsp_InitKeyHard
* 功能说明: 配置按键对应的GPIO
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void bsp_InitKeyHard(void)
{
#ifdef _hal
GPIO_InitTypeDef gpio_init_struct; /* GPIO配置参数存储变量 */
KEY1_GPIO_CLK_ENABLE();
KEY2_GPIO_CLK_ENABLE();
KEY3_GPIO_CLK_ENABLE();
KEY4_GPIO_CLK_ENABLE(); /*按键时钟使能*/
gpio_init_struct.Pin = GPIO_PIN_K1; /* KEY1引脚 */
gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 输入 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(GPIO_PORT_K1, &gpio_init_struct); /* KEY1引脚模式设置,上拉输入 */
gpio_init_struct.Pin = GPIO_PIN_K2; /* KEY2引脚 */
gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 输入 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(GPIO_PORT_K2, &gpio_init_struct); /* KEY2引脚模式设置,上拉输入 */
gpio_init_struct.Pin = GPIO_PIN_K3; /* KEY3引脚 */
gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 输入 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(GPIO_PORT_K3, &gpio_init_struct); /* KEY3引脚模式设置,上拉*/
gpio_init_struct.Pin = GPIO_PIN_K4; /* KEY4引脚 */
gpio_init_struct.Mode = GPIO_MODE_INPUT; /* 输入 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(GPIO_PORT_K4, &gpio_init_struct); /* KEY4引脚模式设置,上拉*/
#else
GPIO_InitTypeDef GPIO_InitStructure;
/* 第1步:打开GPIO时钟 */
RCC_AHB1PeriphClockCmd(RCC_ALL_KEY, ENABLE);
/* 第2步:配置所有的按键GPIO为浮动输入模式(实际上CPU复位后就是输入状态) */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; /* 设为输入口 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /* 设为推挽模式 */
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; /* 无需上下拉电阻 */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* IO口最大速度 */
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K1;
GPIO_Init(GPIO_PORT_K1, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K2;
GPIO_Init(GPIO_PORT_K2, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K3;
GPIO_Init(GPIO_PORT_K3, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K4;
GPIO_Init(GPIO_PORT_K4, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K5;
GPIO_Init(GPIO_PORT_K5, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K6;
GPIO_Init(GPIO_PORT_K6, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K7;
GPIO_Init(GPIO_PORT_K7, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K8;
GPIO_Init(GPIO_PORT_K8, &GPIO_InitStructure);
#endif
}
/*
*********************************************************************************************************
* 函 数 名: bsp_InitKeyVar
* 功能说明: 初始化按键变量
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void bsp_InitKeyVar(void)
{
uint8_t i;
/* 对按键FIFO读写指针清零 */
s_tKey.Read = 0;
s_tKey.Write = 0;
s_tKey.Read2 = 0;
/* 给每个按键结构体成员变量赋一组缺省值 */
for (i = 0; i < KEY_COUNT; i++)
{
s_tBtn[i].LongTime = KEY_LONG_TIME; /* 长按时间 0 表示不检测长按键事件 */
s_tBtn[i].Count = KEY_FILTER_TIME / 2; /* 计数器设置为滤波时间的一半 */
s_tBtn[i].State = 0; /* 按键缺省状态,0为未按下 */
//s_tBtn[i].KeyCodeDown = 3 * i + 1; /* 按键按下的键值代码 */
//s_tBtn[i].KeyCodeUp = 3 * i + 2; /* 按键弹起的键值代码 */
//s_tBtn[i].KeyCodeLong = 3 * i + 3; /* 按键被持续按下的键值代码 */
s_tBtn[i].RepeatSpeed = 0; /* 按键连发的速度,0表示不支持连发 */
s_tBtn[i].RepeatCount = 0; /* 连发计数器 */
}
/* 如果需要单独更改某个按键的参数,可以在此单独重新赋值 */
/* 比如,我们希望按键1按下超过1秒后,自动重发相同键值 */
s_tBtn[KID_JOY_U].LongTime = 100;
s_tBtn[KID_JOY_U].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
s_tBtn[KID_JOY_D].LongTime = 100;
s_tBtn[KID_JOY_D].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
s_tBtn[KID_JOY_L].LongTime = 100;
s_tBtn[KID_JOY_L].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
s_tBtn[KID_JOY_R].LongTime = 100;
s_tBtn[KID_JOY_R].RepeatSpeed = 5; /* 每隔50ms自动发送键值 */
/* 判断按键按下的函数 */
s_tBtn[0].IsKeyDownFunc = IsKeyDown1;
s_tBtn[1].IsKeyDownFunc = IsKeyDown2;
s_tBtn[2].IsKeyDownFunc = IsKeyDown3;
s_tBtn[3].IsKeyDownFunc = IsKeyDown4;
// s_tBtn[4].IsKeyDownFunc = IsKeyDown5;
// s_tBtn[5].IsKeyDownFunc = IsKeyDown6;
// s_tBtn[6].IsKeyDownFunc = IsKeyDown7;
// s_tBtn[7].IsKeyDownFunc = IsKeyDown8;
// /* 组合键 */
// s_tBtn[8].IsKeyDownFunc = IsKeyDown9;
// s_tBtn[9].IsKeyDownFunc = IsKeyDown10;
}
/*
*********************************************************************************************************
* 函 数 名: bsp_DetectKey
* 功能说明: 检测一个按键。非阻塞状态,必须被周期性的调用。
* 形 参: 按键结构变量指针
* 返 回 值: 无
*********************************************************************************************************
*/
static void bsp_DetectKey(uint8_t i)
{
KEY_T *pBtn;
/*
如果没有初始化按键函数,则报错
if (s_tBtn[i].IsKeyDownFunc == 0)
{
printf("Fault : DetectButton(), s_tBtn[i].IsKeyDownFunc undefine");
}
*/
pBtn = &s_tBtn[i];
if (pBtn->IsKeyDownFunc())
{
if (pBtn->Count < KEY_FILTER_TIME)
{
pBtn->Count = KEY_FILTER_TIME;
}
else if(pBtn->Count < 2 * KEY_FILTER_TIME)
{
pBtn->Count++;
}
else
{
if (pBtn->State == 0)
{
pBtn->State = 1;
/* 发送按钮按下的消息 */
bsp_PutKey((uint8_t)(3 * i + 1));
}
if (pBtn->LongTime > 0)
{
if (pBtn->LongCount < pBtn->LongTime)
{
/* 发送按钮持续按下的消息 */
if (++pBtn->LongCount == pBtn->LongTime)
{
/* 键值放入按键FIFO */
bsp_PutKey((uint8_t)(3 * i + 3));
}
}
else
{
if (pBtn->RepeatSpeed > 0)
{
if (++pBtn->RepeatCount >= pBtn->RepeatSpeed)
{
pBtn->RepeatCount = 0;
/* 常按键后,每隔10ms发送1个按键 */
bsp_PutKey((uint8_t)(3 * i + 1));
}
}
}
}
}
}
else
{
if(pBtn->Count > KEY_FILTER_TIME)
{
pBtn->Count = KEY_FILTER_TIME;
}
else if(pBtn->Count != 0)
{
pBtn->Count--;
}
else
{
if (pBtn->State == 1)
{
pBtn->State = 0;
/* 发送按钮弹起的消息 */
bsp_PutKey((uint8_t)(3 * i + 2));
}
}
pBtn->LongCount = 0;
pBtn->RepeatCount = 0;
}
}
/*
*********************************************************************************************************
* 函 数 名: bsp_KeyScan
* 功能说明: 扫描所有按键。非阻塞,被systick中断周期性的调用
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_KeyScan(void)
{
uint8_t i;
for (i = 0; i < KEY_COUNT; i++)
{
bsp_DetectKey(i);
}
}
key.h
/*请在操作系统下使用本程序*/
#ifndef __KEY_H
#define __KEY_H
#include "./SYSTEM/sys/sys.h"
/*此处请保持与实际按键个数相同否则会卡死*/
#define KEY_COUNT 4 /* 按键个数, 8个独立建 + 2个组合键 */
/*低电平表示按下*/
#define _hal 1 /*使用hal库请置1标准库为其余任意值*/
/* 根据应用程序的功能重命名按键宏 */
#define KEY_DOWN_K1 KEY_1_DOWN
#define KEY_UP_K1 KEY_1_UP
#define KEY_LONG_K1 KEY_1_LONG
#define KEY_DOWN_K2 KEY_2_DOWN
#define KEY_UP_K2 KEY_2_UP
#define KEY_LONG_K2 KEY_2_LONG
#define KEY_DOWN_K3 KEY_3_DOWN
#define KEY_UP_K3 KEY_3_UP
#define KEY_LONG_K3 KEY_3_LONG
#define KEY_DOWN_K4 KEY_4_DOWN
#define KEY_UP_K4 KEY_4_UP
#define KEY_LONG_K4 KEY_4_LONG
#define JOY_DOWN_U KEY_5_DOWN /* 上 */
#define JOY_UP_U KEY_5_UP
#define JOY_LONG_U KEY_5_LONG
#define JOY_DOWN_D KEY_6_DOWN /* 下 */
#define JOY_UP_D KEY_6_UP
#define JOY_LONG_D KEY_6_LONG
#define JOY_DOWN_L KEY_7_DOWN /* 左 */
#define JOY_UP_L KEY_7_UP
#define JOY_LONG_L KEY_7_LONG
#define JOY_DOWN_R KEY_8_DOWN /* 右 */
#define JOY_UP_R KEY_8_UP
#define JOY_LONG_R KEY_8_LONG
#define JOY_DOWN_OK KEY_9_DOWN /* ok */
#define JOY_UP_OK KEY_9_UP
#define JOY_LONG_OK KEY_9_LONG
#define SYS_DOWN_K1K2 KEY_10_DOWN /* K1 K2 组合键 */
#define SYS_UP_K1K2 KEY_10_UP
#define SYS_LONG_K1K2 KEY_10_LONG
#define SYS_DOWN_K2K3 KEY_11_DOWN /* K2 K3 组合键 */
#define SYS_UP_K2K3 KEY_11_UP
#define SYS_LONG_K2K3 KEY_11_LONG
/*请在下面修改按键适配程序*/
#ifdef _hal
#define GPIO_PORT_K1 GPIOA
#define GPIO_PIN_K1 GPIO_PIN_0
#define KEY1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */
#define GPIO_PORT_K2 GPIOB
#define GPIO_PIN_K2 GPIO_PIN_3
#define KEY2_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PE口时钟使能 */
#define GPIO_PORT_K3 GPIOC
#define GPIO_PIN_K3 GPIO_PIN_2
#define KEY3_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0) /* PE口时钟使能 */
#define GPIO_PORT_K4 GPIOC
#define GPIO_PIN_K4 GPIO_PIN_0
#define KEY4_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0) /* PA口时钟使能 */
#define RCC_ALL_KEY do{__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();}while(0)/*全部按键使能*/
#else
#define RCC_ALL_KEY (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOH | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOG)
#define GPIO_PORT_K1 GPIOI
#define GPIO_PIN_K1 GPIO_Pin_8
#define GPIO_PORT_K2 GPIOC
#define GPIO_PIN_K2 GPIO_Pin_13
#define GPIO_PORT_K3 GPIOI
#define GPIO_PIN_K3 GPIO_Pin_11
#define GPIO_PORT_K4 GPIOH
#define GPIO_PIN_K4 GPIO_Pin_2
#endif
/* 按键ID, 主要用于bsp_KeyState()函数的入口参数 */
typedef enum
{
KID_K1 = 0,
KID_K2,
KID_K3,
KID_K4,
//以下为遥感按键可以不用
KID_JOY_U,
KID_JOY_D,
KID_JOY_L,
KID_JOY_R,
KID_JOY_OK
}KEY_ID_E;
/*
按键滤波时间50ms, 单位10ms。
只有连续检测到50ms状态不变才认为有效,包括弹起和按下两种事件
即使按键电路不做硬件滤波,该滤波机制也可以保证可靠地检测到按键事件
*/
#define KEY_FILTER_TIME 5 /*可以自行修改最好不要小于2(若未使用rtos请使用定时器10ms调用一次,若使用请加上10ms的延时)*/
#define KEY_LONG_TIME 100 /* 单位10ms, 持续1秒,认为长按事件 */
/*
每个按键对应1个全局的结构体变量。
*/
typedef struct
{
/* 下面是一个函数指针,指向判断按键手否按下的函数 */
uint8_t (*IsKeyDownFunc)(void); /* 按键按下的判断函数,1表示按下 */
uint8_t Count; /* 滤波器计数器 */
uint16_t LongCount; /* 长按计数器 */
uint16_t LongTime; /* 按键按下持续时间, 0表示不检测长按 */
uint8_t State; /* 按键当前状态(按下还是弹起) */
uint8_t RepeatSpeed; /* 连续按键周期 */
uint8_t RepeatCount; /* 连续按键计数器 */
}KEY_T;
/*
定义键值代码, 必须按如下次序定时每个键的按下、弹起和长按事件
推荐使用enum, 不用#define,原因:
(1) 便于新增键值,方便调整顺序,使代码看起来舒服点
(2) 编译器可帮我们避免键值重复。
*/
typedef enum
{
KEY_NONE = 0, /* 0 表示按键事件 */
KEY_1_DOWN, /* 1键按下 */
KEY_1_UP, /* 1键弹起 */
KEY_1_LONG, /* 1键长按 */
KEY_2_DOWN, /* 2键按下 */
KEY_2_UP, /* 2键弹起 */
KEY_2_LONG, /* 2键长按 */
KEY_3_DOWN, /* 3键按下 */
KEY_3_UP, /* 3键弹起 */
KEY_3_LONG, /* 3键长按 */
KEY_4_DOWN, /* 4键按下 */
KEY_4_UP, /* 4键弹起 */
KEY_4_LONG, /* 4键长按 */
KEY_5_DOWN, /* 5键按下 */
KEY_5_UP, /* 5键弹起 */
KEY_5_LONG, /* 5键长按 */
KEY_6_DOWN, /* 6键按下 */
KEY_6_UP, /* 6键弹起 */
KEY_6_LONG, /* 6键长按 */
KEY_7_DOWN, /* 7键按下 */
KEY_7_UP, /* 7键弹起 */
KEY_7_LONG, /* 7键长按 */
KEY_8_DOWN, /* 8键按下 */
KEY_8_UP, /* 8键弹起 */
KEY_8_LONG, /* 8键长按 */
/* 组合键 */
KEY_9_DOWN, /* 9键按下 */
KEY_9_UP, /* 9键弹起 */
KEY_9_LONG, /* 9键长按 */
KEY_10_DOWN, /* 10键按下 */
KEY_10_UP, /* 10键弹起 */
KEY_10_LONG, /* 10键长按 */
}KEY_ENUM;
/* 按键FIFO用到变量 */
#define KEY_FIFO_SIZE 11
typedef struct
{
uint8_t Buf[KEY_FIFO_SIZE]; /* 键值缓冲区 */
uint8_t Read; /* 缓冲区读指针1 */
uint8_t Write; /* 缓冲区写指针 */
uint8_t Read2; /* 缓冲区读指针2 */
}KEY_FIFO_T;
/* 供外部调用的函数声明 */
void bsp_InitKey(void);
void bsp_KeyScan(void);
void bsp_PutKey(uint8_t _KeyCode);
uint8_t bsp_GetKey(void);
uint8_t bsp_GetKey2(void);
uint8_t bsp_GetKeyState(KEY_ID_E _ucKeyID);
void bsp_SetKeyParam(uint8_t _ucKeyID, uint16_t _LongTime, uint8_t _RepeatSpeed);
void bsp_ClearKey(void);
#endif