/* * 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); } }