452 lines
11 KiB
C
452 lines
11 KiB
C
/*
|
||
* key.c
|
||
*
|
||
* Created on: Sep 25, 2022
|
||
* Author: wyf
|
||
*/
|
||
/*
|
||
* key.c
|
||
*
|
||
* Created on: 2022年6月23日
|
||
* Author: wyf
|
||
*/
|
||
|
||
#include "user.h"
|
||
#include "user_key.h"
|
||
|
||
#define KEY_COUNT 5 /* 实体按键个数 */
|
||
|
||
/* 依次定义GPIO */
|
||
typedef struct
|
||
{
|
||
GPIO_TypeDef* gpio;
|
||
uint16_t pin;
|
||
uint8_t ActiveLevel; /* 激活电平 */
|
||
}X_GPIO_T;
|
||
|
||
/* GPIO和PIN定义 */
|
||
static const X_GPIO_T s_gpio_list[KEY_COUNT] = {
|
||
{Key_UP_GPIO_Port, Key_UP_Pin, 0},
|
||
{KEY_Down_GPIO_Port, KEY_Down_Pin, 0},
|
||
{Key_OK_GPIO_Port, Key_OK_Pin, 0},
|
||
{Key_Reset_GPIO_Port,Key_Reset_Pin, 0},
|
||
{KEY_PWR_GPIO_Port,KEY_PWR_Pin, 1},
|
||
|
||
};
|
||
|
||
/* 定义一个宏函数简化后续代码
|
||
判断GPIO引脚是否有效按下
|
||
*/
|
||
static KEY_T s_tBtn[KEY_COUNT] = {0};
|
||
static KEY_FIFO_T s_tKey; /* 按键FIFO变量,结构体 */
|
||
|
||
static void bsp_InitKeyVar(void);
|
||
static void bsp_DetectKey(uint8_t i);
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* 函 数 名: KeyPinActive
|
||
* 功能说明: 判断按键是否按下
|
||
* 形 参: 无
|
||
* 返 回 值: 返回值1 表示按下(导通),0表示未按下(释放)
|
||
*********************************************************************************************************
|
||
*/
|
||
static uint8_t KeyPinActive(uint8_t _id)
|
||
{
|
||
uint8_t level;
|
||
|
||
if ((s_gpio_list[_id].gpio->IDR & s_gpio_list[_id].pin) == 0)
|
||
{
|
||
level = 0;
|
||
}
|
||
else
|
||
{
|
||
level = 1;
|
||
}
|
||
|
||
if (level == s_gpio_list[_id].ActiveLevel)
|
||
{
|
||
return 1;
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* 函 数 名: IsKeyDownFunc
|
||
* 功能说明: 判断按键是否按下。单键和组合键区分。单键事件不允许有其他键按下。
|
||
* 形 参: 无
|
||
* 返 回 值: 返回值1 表示按下(导通),0表示未按下(释放)
|
||
*********************************************************************************************************
|
||
*/
|
||
static uint8_t IsKeyDownFunc(uint8_t _id)
|
||
{
|
||
/* 实体单键 */
|
||
if (_id < KEY_COUNT)
|
||
{
|
||
if (KeyPinActive(_id))
|
||
{
|
||
return 1;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* 函 数 名: bsp_InitKey
|
||
* 功能说明: 初始化按键. 该函数被 bsp_Init() 调用。
|
||
* 形 参: 无
|
||
* 返 回 值: 无
|
||
*********************************************************************************************************
|
||
*/
|
||
void Init_Key(void)
|
||
{
|
||
bsp_InitKeyVar(); /* 初始化按键变量 */
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* 函 数 名: 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].RepeatSpeed = 4; /* 按键连发的速度,0表示不支持连发 */
|
||
s_tBtn[i].RepeatCount = 0; /* 连发计数器 */
|
||
}
|
||
|
||
/* 如果需要单独更改某个按键的参数,可以在此单独重新赋值 */
|
||
|
||
}
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* 函 数 名: 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_DetectKey
|
||
* 功能说明: 检测一个按键。非阻塞状态,必须被周期性的调用。
|
||
* 形 参: IO的id, 从0开始编码
|
||
* 返 回 值: 无
|
||
*********************************************************************************************************
|
||
*/
|
||
static void bsp_DetectKey(uint8_t i)
|
||
{
|
||
KEY_T *pBtn;
|
||
|
||
pBtn = &s_tBtn[i];
|
||
if (IsKeyDownFunc(i))
|
||
{
|
||
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_DetectFastIO
|
||
* 功能说明: 检测高速的输入IO. 1ms刷新一次
|
||
* 形 参: IO的id, 从0开始编码
|
||
* 返 回 值: 无
|
||
*********************************************************************************************************
|
||
*/
|
||
static void bsp_DetectFastIO(uint8_t i)
|
||
{
|
||
KEY_T *pBtn;
|
||
|
||
pBtn = &s_tBtn[i];
|
||
if (IsKeyDownFunc(i))
|
||
{
|
||
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->State == 1)
|
||
{
|
||
pBtn->State = 0;
|
||
|
||
/* 发送按钮弹起的消息 */
|
||
bsp_PutKey((uint8_t)(3 * i + 2));
|
||
}
|
||
|
||
pBtn->LongCount = 0;
|
||
pBtn->RepeatCount = 0;
|
||
}
|
||
}
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* 函 数 名: bsp_KeyScan10ms
|
||
* 功能说明: 扫描所有按键。非阻塞,被systick中断周期性的调用,10ms一次
|
||
* 形 参: 无
|
||
* 返 回 值: 无
|
||
*********************************************************************************************************
|
||
*/
|
||
void bsp_KeyScan10ms(void)
|
||
{
|
||
uint8_t i;
|
||
|
||
for (i = 0; i < KEY_COUNT; i++)
|
||
{
|
||
bsp_DetectKey(i);
|
||
}
|
||
}
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* 函 数 名: bsp_KeyScan1ms
|
||
* 功能说明: 扫描所有按键。非阻塞,被systick中断周期性的调用,1ms一次.
|
||
* 形 参: 无
|
||
* 返 回 值: 无
|
||
*********************************************************************************************************
|
||
*/
|
||
void bsp_KeyScan1ms(void)
|
||
{
|
||
uint8_t i;
|
||
|
||
for (i = 0; i < KEY_COUNT; i++)
|
||
{
|
||
bsp_DetectFastIO(i);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|