|
本帖最后由 czm_hyt@163.com 于 2020-6-17 17:22 编辑
本人刚学习STM32开发,最近看了硬汉的按键检测程序,进行了架构的深度优化,所以跟大家分享一下:本人使用的STM32F103,有6个独立的按键;A、B、C、D、OK、Power,目前实现的功能如下:
1:单键短按,长按,连发,双击,3连击。。。。。最多不限制;
2:各种组合按键,组合按键的短按,长按,连发,组合按键的双击,连击;
3:这些功能都可以随意配置;
性能测试,STM32使用内部时钟,64M,有按键的时候,按键扫描函数执行时间是12us;
程序先不跟大家分享了,分享一下我对按键扫描的理解和实现的大概流程:
*********************************************************************************************************
* 虚拟按键扫描功能说明:V1.0-2019.12.30
按键定义:单键/多键;单击/组合(连击);短按/长按;连发;
注:对于应用层来说,组合也是单击,不需要标识出来。A和B组合生效,可以单键A和单键B组合,也可以是多键AB单击;
定义说明:
1: 单键/多键:只有1个按键变化;多键:2个及以上的按键同变化(变化的时间接近即可,底层滤波自动处理,总线滤波参数控制);
后文中提到的“按键”,包括单键或者多键,多键也可以称之为一个按键!!!,大家认为的组合按键的双击,我们称之为多键连击;
“不同的按键”不能有相同的部分,如单键A,和多键AB不是不相同的按键;
2: 单击:设定的时间内,有按键(单键或多键)按下1次;如不支持连击/组合,单击:有按键(单键或多键)按下1次;
3: 组合:设定的时间内,有多个不同的按键(单键或者多键)按下1次;单键和单键,单键和多键,多键和多键都可以组合;
4: 连击:设定的时间内,相同的按键(单键或多键)按下2次及以上;
5: 长按:单击/组合/连击发生后,并且持续稳定的时间超过设定的时间阈值;
6: 连发:单击/组合/连击长按之后,按照设定的周期,不断的产生单击/组合/连击事件;
注:设定的时间内,要么发生连击,要么发生不同的按键进行组合,两者为互斥事件;
按照时间顺序排列,有几个按键(单键还是多键),是单击还是组合还是连击,稳定之后是长按,还是短按,长按之后是否连发;
按键扫描流程:
1: 将物理按键映射到逻辑按键上,多个按键映射成并口的数据通道,按键检测,转换成采集通道上的数据。
2: 某一个数据线上不用独立滤波,而是进行总线数据滤波。也就是多个按键一起滤波;
3: 组合/连击:总线上有数据时(有按键按下后),开始定时,发生数据变化时(又有按键按下),判断是组合,还是连击,
连击是只指相同的按键,组合是指不同的按键; 连击时,按键次数增加,组合时,有效按键个数增加,组合和连击,只能发生一个;
4: 连击时,可以复位定时器,组合时,可以不复位,也可以复位,正常不需要复位;
*********************************************************************************************************
欢迎各位群友交流讨论,共同进步!
- /*******************************************************************************
- * Copyright (C), 1993-2012, Liming Comm. Co., Ltd.
- * @file :RM_KEY.c
- * @brief :虚拟按键扫描
- * @author :czm_hyt@163.com
- * @version :V1.0
- * @date :2019-11-15
- * @time :20:22:35
- *
-
- ******************************************************************************
- * 函数列表
- *
- * 1. Enter the name of the first function
- * 2. Enter the name of the second function
- ******************************************************************************
- * 修改历史
- *
- * 2019-11-15 czm 建立文件
- *******************************************************************************/
- /*
- *********************************************************************************************************
- * 虚拟按键扫描功能说明:V1.0-2019.12.30
- 按键定义:单键/多键;单击/组合(连击);短按/长按;连发;
- 注:对于应用层来说,组合也是单击,不需要标识出来。A和B组合生效,可以单键A和单键B组合,也可以是多键AB单击;
- 定义说明:
- 1: 单键/多键:只有1个按键变化;多键:2个及以上的按键同变化(变化的时间接近即可,底层滤波自动处理,总线滤波参数控制);
- 后文中提到的“按键”,包括单键或者多键,多键也可以称之为一个按键!!!,大家认为的组合按键的双击,我们称之为多键连击;
- “不同的按键”不能有相同的部分,如单键A,和多键AB不是不相同的按键;
- 2: 单击:设定的时间内,有按键(单键或多键)按下1次;如不支持连击/组合,单击:有按键(单键或多键)按下1次;
- 3: 组合:设定的时间内,有多个不同的按键(单键或者多键)按下1次;单键和单键,单键和多键,多键和多键都可以组合;
- 4: 连击:设定的时间内,相同的按键(单键或多键)按下2次及以上;
- 5: 长按:单击/组合/连击发生后,并且持续稳定的时间超过设定的时间阈值;
- 6: 连发:单击/组合/连击长按之后,按照设定的周期,不断的产生单击/组合/连击事件;
- 注:设定的时间内,要么发生连击,要么发生不同的按键进行组合,两者为互斥事件;
- 按照时间顺序排列,有几个按键(单键还是多键),是单击还是组合还是连击,稳定之后是长按,还是短按,长按之后是否连发;
- 按键扫描流程:
- 1: 将物理按键映射到逻辑按键上,多个按键映射成并口的数据通道,按键检测,转换成采集通道上的数据。
- 2: 某一个数据线上不用独立滤波,而是进行总线数据滤波。
- 3: 组合/连击:总线上有数据时(有按键按下后),开始定时,发生数据变化时(又有按键按下),判断是组合,还是连击,
- 连击是只指相同的按键,组合是指不同的按键; 连击时,按键次数增加,组合时,有效按键个数增加,组合和连击,只能发生一个;
- 4: 连击时,可以复位定时器,组合时,可以不复位,也可以复位,正常不需要复位;
-
- *********************************************************************************************************
- */
- #include "RM_KEY.h"
- static RM_KEY_CONFIG_T s_RM_KEY_CFG = {0};
- // RM 硬件键实时运行状态
- static RM_KEY_RUN_DATA_T s_tRmKeyRunData = {0};
- // 硬件按键GPIO和PIN定义
- static const RM_KEY_GPIO_DEF_T s_atRmKeyGpioDef[RM_HARD_KEY_NUM] =
- {
- // 按键都是高电平有效 TRUE
- {GPIOA, GPIO_Pin_4, TRUE}, // KEY A 按键 PA4
- {GPIOC, GPIO_Pin_0, TRUE}, // KEY B 按键 PC0
- {GPIOC, GPIO_Pin_15, TRUE}, // KEY C 按键 PC15
- {GPIOC, GPIO_Pin_5, TRUE}, // KEY D 按键 PC5
- {GPIOC, GPIO_Pin_14, TRUE}, // KEY OK 按键 PC14
- {GPIOA, GPIO_Pin_0, TRUE}, // Power 按键 PA0
- };
- /**
- * @brief 虚拟按键转化表,将所有实体按键都转换成一个bit
- */
- static const u8 s_auKeyBitDef[RM_HARD_KEY_NUM] =
- {
- // 单按键定义 A、B、C、D、OK、Power
- 0x01, 0x02, 0x04, 0x08, 0x010, 0x20,
- // 组合按键定义
- };
- // 可以用于LCD 没有操作时息屏 有操作时亮屏
- ///* 用于按键超时进入屏保 */
- //static int32_t s_KeyTimeOutCount = 0;
- //static uint8_t s_LcdOn = 1;
- /**
- * @brief 计算8位数据中1的个数
- *
- * @param [in] uData 需要计算的数据,8位
- *
- * @return 数据中1的个数
- * @author
- * @since trunk.00001
- * @bug
- */
- u8 Ones8(u8 uData)
- {
- uData -= ((uData >> 1) & 0x55);
- uData = (((uData >> 2) & 0x33) + (uData & 0x33));
- uData += (uData >> 4);
- return (uData & 0x0F);
- }
- /**
- * @brief 判断单独按键管脚是否有效 对上屏蔽底层 对上TRUE就是有效,FALSE就是弹开
- *
- * @param [in] nKeyID 按键ID 0 ~ RM_HARD_KEY_NUM-1
- *
- * @return TRUE:按键有效;FALSE:按键无效
- * @author
- * @since trunk.00001
- * @bug
- */
- static BOOL RM_KEY_IsActive(RM_KEY_ID_E nKeyID)
- {
- BOOL bPinLevel;
- // 判断按键管脚IO电平 TRUE:高电平
- if (s_atRmKeyGpioDef[nKeyID].ptGpio->IDR & s_atRmKeyGpioDef[nKeyID].u2Pin)
- {
- bPinLevel = TRUE;
- }
- else
- {
- bPinLevel = FALSE;
- }
- if (bPinLevel == s_atRmKeyGpioDef[nKeyID].bActiveLevel)
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- }
- // A和B如果几乎同时按下 滤波时间会增加2倍数,此时认为AB是同时按下的
- /**
- * @brief 更新按键管脚状态 带逻辑整体滤波 非物理
- * @brief 将每一个实体按键转化成1 bit,便于虚拟按键映射
- *
- * @param [in] nKeyID 按键ID 0 ~ RM_HARD_KEY_NUM-1
- *
- * @return TRUE:按键有效;FALSE:按键无效
- * @author
- * @since trunk.00001
- * @bug
- */
- // 需要优化
- static void RM_KEY_Update(void)
- {
- static u8 s_uRmKeyBusData = 0; // 上一次Key总线数据
- u8 uRmKeyBusData_New = 0; // 最新Key总线数据
- u8 uTemp = 0;
-
- // 按键按下,对应比特置1,物理按键转逻辑按键
- for (uTemp = 0; uTemp < RM_HARD_KEY_NUM; uTemp++)
- {
- if (RM_KEY_IsActive(uTemp))
- {
- uRmKeyBusData_New |= s_auKeyBitDef[uTemp];
- }
- }
- // 滤波的定义:相同状态持续设置的阈值 状态就生效
- if (s_uRmKeyBusData == uRmKeyBusData_New) // 最新状态与上次的状态相同,计数判断稳定时间
- {
- if (s_RM_KEY_CFG.uFilterCtr > s_tRmKeyRunData.uFIlterCount)
- {
- s_tRmKeyRunData.uFIlterCount++;
- }
- else if (s_RM_KEY_CFG.uFilterCtr == s_tRmKeyRunData.uFIlterCount) // 稳定时间达到滤波阈值
- {
- s_RM_KEY_CFG.uRmKeyBusData = uRmKeyBusData_New; // 更新最新的按键状态
- s_RM_KEY_CFG.uKeyBusDataCnt = Ones8(s_RM_KEY_CFG.uRmKeyBusData);
- s_tRmKeyRunData.uFIlterCount++; // 只更新一次
- }
- // 按键总线数据稳定后,也要判断是否与记录的状态同步
- else if (uRmKeyBusData_New != s_RM_KEY_CFG.uRmKeyBusData)
- {
- s_tRmKeyRunData.uFIlterCount = 0; // 状态不同步 启动滤波更新
- }
- }
- else // 状态只要发生变化,就启动一次状态更新
- {
- s_tRmKeyRunData.uFIlterCount = 0; // 启动一次状态更新 带滤波
- s_uRmKeyBusData = uRmKeyBusData_New; // 状态发生变化 更新保存
- }
- }
- /**
- * @brief 将1个键值压入按键FIFO缓冲区。可用于模拟一个按键。
- *
- * @param [in] nKeyMsgCode 按键代码
- *
- * @return 无
- * @author
- * @since trunk.00001
- * @bug
- */
- void RM_KEY_PutKeyMsg(u16 u2KeyMsgCode)
- {
- // 有按键按下 可以开屏幕背光 进行省点相关操作
-
- s_tRmKeyRunData.u2MsgBuf[s_tRmKeyRunData.uWriteAddr] = u2KeyMsgCode;
- if (RM_KEY_MSG_FIFO_SIZE <= (++s_tRmKeyRunData.uWriteAddr))
- {
- s_tRmKeyRunData.uWriteAddr = 0;
- }
-
- // s_KeyTimeOutCount = GetSleepTimeMinute() * 60 * 100u; /* 10ms单位 */
- }
- //{
- //// /* 屏幕熄灭阶段,丢弃唤醒键 */
- //// if (s_LcdOn == 0)
- //// {
- //// u8 key;
- ////
- //// key = ((_KeyCode - 1) % KEY_MSG_STEP) + 1;
- //// if (key == KEY_1_UP || key == KEY_1_LONG_UP)
- //// {
- //// s_LcdOn = 1;
- //// }
- ////// LCD_DispOn();
- ////// LCD_SetBackLight(BRIGHT_DEFAULT); /* 打开背光 */
- //// return;
- //// }
- //
- // s_RM_KEY_CFG.uMsgBuf[s_RM_KEY_CFG.uWriteAddr] = nKeyMsgCode;
- // if (RM_KEY_MSG_FIFO_SIZE <= (++s_RM_KEY_CFG.uWriteAddr))
- // {
- // s_RM_KEY_CFG.uWriteAddr = 0;
- // }
- //
- //// s_KeyTimeOutCount = GetSleepTimeMinute() * 60 * 100u; /* 10ms单位 */
- //}
- /**
- * @brief 从按键FIFO缓冲区读取一个键值。
- *
- * @param [in] 无
- *
- * @return 按键代码
- * @author
- * @since trunk.00001
- * @bug
- */
- u16 RM_KEY_GetKeyMsgA(void)
- {
- u16 u2MsgCode = 0x0000;
-
- // 判断是否有按键消息
- if (s_tRmKeyRunData.uWriteAddr != s_tRmKeyRunData.uReadAddrA)
- {
- u2MsgCode = s_tRmKeyRunData.u2MsgBuf[s_tRmKeyRunData.uReadAddrA];
-
- // 读消息地址指针保护
- if (RM_KEY_MSG_FIFO_SIZE <= (++s_tRmKeyRunData.uReadAddrA))
- {
- s_tRmKeyRunData.uReadAddrA = 0;
- }
- }
- return u2MsgCode;
- }
- /**
- * @brief 从按键FIFO缓冲区读取一个键值。
- * @brief 两个函数调用不冲突?
- *
- * @param [in] 无
- *
- * @return 按键代码
- * @author
- * @since trunk.00001
- * @bug
- */
- u16 RM_KEY_GetKeyMsgB(void)
- {
- u16 u2MsgCode = 0x0000;
-
- // 判断是否有按键消息
- if (s_tRmKeyRunData.uWriteAddr != s_tRmKeyRunData.uReadAddrB)
- {
- // 有消息,则读取消息
- u2MsgCode = s_tRmKeyRunData.u2MsgBuf[s_tRmKeyRunData.uReadAddrB];
-
- // 读消息地址指针保护
- if (RM_KEY_MSG_FIFO_SIZE <= (++s_tRmKeyRunData.uReadAddrB))
- {
- s_tRmKeyRunData.uReadAddrB = 0;
- }
- }
- return u2MsgCode;
- }
- /**
- * @brief 读取最新按键状态
- *
- * @param [in] 无
- *
- * @return 当前最新按键数据
- * @author
- * @since trunk.00001
- * @bug
- */
- u8 RM_KEY_GetKeyState(void)
- {
- return s_RM_KEY_CFG.uRmKeyBusData;
- }
- /**
- * @brief 读取按键的状态
- *
- * @param [in] nKeyID // 按键逻辑ID
- * @param [in] uCombCtr // 组合、连击
- * @param [in] uLongCtr // 长按
- * @param [in] uRepeatCtr // 连发
- *
- * @return 无
- * @author
- * @since trunk.00001
- * @bug
- */
- void RM_KEY_SetKeyParam(u8 uFilterCtr, u8 uCombCtr, u8 uClickCtr, u8 uLongCtr, u8 uRepeatCtr, u8 uIdleCtr)
- {
- s_RM_KEY_CFG.uFilterCtr = uFilterCtr; // 按键底层总线滤波,按键接近时,可滤波成同时按下,既多键
-
- s_RM_KEY_CFG.uCombCtr = uCombCtr; // 组合、连击等待时间阈值 0 表示不支持,最大2.5s
- s_RM_KEY_CFG.uClickCtr = uClickCtr & 0x07; // 连击最大次数,必须支持组合/连击时才生效 最小值2 最大值7
-
- s_RM_KEY_CFG.uLongCtr = uLongCtr; // 长按计数器 等待阈值 0 表示不支持,最大2.5s
- s_RM_KEY_CFG.uRepeatCtr = uRepeatCtr; // 长按连续发送阈值, 0 表示不支持,最大2.5s,必须支持长按时才生效
-
- s_RM_KEY_CFG.uIdleCtr = uIdleCtr; // 按键弹开后,如何进入IDLE模式,0:必须没有按键才能进入,其它:延时对应时间,强制进IDLE
- }
- /**
- * @brief 设置按键默认初始化参数
- *
- * @param [in] 无
- *
- * @return 当前最新按键数据
- * @author
- * @since trunk.00001
- * @bug
- */
- void RM_KEY_SetKeyParamDefault(void)
- {
- s_RM_KEY_CFG.uRmKeyBusData = 0;
- s_RM_KEY_CFG.uKeyBusDataCnt = 0;
-
- s_RM_KEY_CFG.uFilterCtr = RM_KEY_FILTER_TIME; // 按键底层总线滤波,按键接近时,可滤波成同时按下,既多键
-
- s_RM_KEY_CFG.uCombCtr = RM_KEY_COMB_TIME; // 组合、连击等待时间阈值 0 表示不支持,最大2.5s
- s_RM_KEY_CFG.uClickCtr = RM_KEY_CLICK_CTR; // 连击最大次数,必须支持组合/连击时才生效 最小值2 最大值7
-
- s_RM_KEY_CFG.uLongCtr = RM_KEY_LONG_TIME; // 长按计数器 等待阈值 0 表示不支持,最大2.5s
- s_RM_KEY_CFG.uRepeatCtr = RM_KEY_REPEAT_TIME; // 长按连续发送阈值, 0 表示不支持,最大2.5s,必须支持长按时才生效
-
- s_RM_KEY_CFG.uClickCtr = RM_KEY_IDLE_TIME; // 单键或组合按键,最多连击的次数
- s_tRmKeyRunData.nGobleState = 0;
- s_tRmKeyRunData.uRmKeyData = 0;
- s_tRmKeyRunData.uRmKeyDataCnt = 0;
-
- s_tRmKeyRunData.uFIlterCount = 0;
-
- s_tRmKeyRunData.uCombCnt = 0;
- s_tRmKeyRunData.uClickCnt = 0;
-
- s_tRmKeyRunData.uLongCnt = 0;
- s_tRmKeyRunData.uRepeatCnt = 0;
-
- s_tRmKeyRunData.uIdleCnt = 0;
- // 按键消息缓存区清零
- s_tRmKeyRunData.uWriteAddr = 0;
- s_tRmKeyRunData.uReadAddrA = 0;
- s_tRmKeyRunData.uReadAddrB = 0;
-
- }
- /**
- * @brief 清空按键FIFO缓冲区
- *
- * @param [in] 无
- *
- * @return 无
- * @author
- * @since trunk.00001
- * @bug
- */
- void RM_KEY_ClearKeyMsg(void)
- {
- s_tRmKeyRunData.uReadAddrA = s_tRmKeyRunData.uWriteAddr;
- }
- // 按键定义:单键/多键;单击/组合(连击);短按/长按;连发;
- // 注:对于应用层来说,组合也是单击,不需要标识出来。A和B组合生效,可以单键A和单键B组合,也可以是多键AB单击;
- /**
- * @brief 读取最新按键状态
- *
- * @param [in] 无
- *
- * @return 当前最新按键数据
- * @author
- * @since trunk.00001
- * @bug
- */
- static void RM_KEY_Detect(void)
- {
- static u8 s_uRmKeyBusData_Last = 0; // 记录上一次按键总线上的数据
- static u16 s_u2CombLongFlag = 0; // 组合/连击 长按/连发 标志
- u8 uRmKeyBusData_Temp = 0;
- switch (s_tRmKeyRunData.nGobleState)
- {
- case RM_KEY_STATE_IDLE:
- {
- // 按键总线上有数据
- if (s_RM_KEY_CFG.uRmKeyBusData)
- {
- s_u2CombLongFlag = 0; // 下面马上要使用到 所以要先初始化
- s_tRmKeyRunData.uCombCnt = 0; // 组合/连击计数器
- s_tRmKeyRunData.uLongCnt = 0; // 长按计数器
- s_tRmKeyRunData.uRepeatCnt = 0; // 连发计数器
-
- // 记录第一个有效按键的总线数据 单键或多键
- s_tRmKeyRunData.uRmKeyData = s_RM_KEY_CFG.uRmKeyBusData;
- s_tRmKeyRunData.uRmKeyDataCnt = s_RM_KEY_CFG.uKeyBusDataCnt;
- s_tRmKeyRunData.uClickCnt = 1; // 第一次按下
- // 支持组合/连击
- if (s_RM_KEY_CFG.uCombCtr)
- {
- s_tRmKeyRunData.nGobleState = RM_KEY_STATE_WAIT_COMB; // 进入等待组合/连击模式
- }
- else
- {
- // 输出单击按键数据
- RM_KEY_PutKeyMsg((u16)s_tRmKeyRunData.uRmKeyData | s_u2CombLongFlag | RM_KEY_MASK_SHORT_D);
- s_tRmKeyRunData.nGobleState = RM_KEY_STATE_WAIT_LONG; // 进入等待长按
- }
- }
- }
- break;
- // 要么是组合要么是连击 组合:按键个数增加;连击:按键次数增加;
- case RM_KEY_STATE_WAIT_COMB:
- {
- // 定时器超时 判断单击/连击 状态是否维持中,组合也是单击
- if (s_RM_KEY_CFG.uCombCtr <= (++s_tRmKeyRunData.uCombCnt))
- {
- // 所有的按键必须是按下状态 s_tRmKeyRunData.uRmKeyData记录所有按下过的按键
- if (s_RM_KEY_CFG.uRmKeyBusData == s_tRmKeyRunData.uRmKeyData)
- {
- // 单击/连击 按下,组合也是单击
- RM_KEY_PutKeyMsg((u16)s_tRmKeyRunData.uRmKeyData | s_u2CombLongFlag | RM_KEY_MASK_SHORT_D);
- s_tRmKeyRunData.nGobleState = RM_KEY_STATE_WAIT_LONG;
- }
- else
- {
- // 单击/连击 按下,组合也是单击
- RM_KEY_PutKeyMsg((u16)s_tRmKeyRunData.uRmKeyData | s_u2CombLongFlag | RM_KEY_MASK_SHORT_D);
-
- s_tRmKeyRunData.nGobleState = RM_KEY_STATE_WAIT_IDLE;
- s_tRmKeyRunData.uIdleCnt = s_RM_KEY_CFG.uIdleCtr;
- }
- }
- else // 除了连击 否则不允许有重复的按键按下
- {
- // 判断按键发生变化的位置 有可能没有按键按下
- uRmKeyBusData_Temp = s_RM_KEY_CFG.uRmKeyBusData ^ s_uRmKeyBusData_Last;
-
- // 判断按键是按下 还是弹开
- uRmKeyBusData_Temp &= s_RM_KEY_CFG.uRmKeyBusData;
- // 判断是否有新的按键按下 新的按键跟之前按键的关系 包含 交集 独立?
-
-
- // 有交集发生 这个交集是中间状态 先判断 进行大的区分
- if (uRmKeyBusData_Temp & s_tRmKeyRunData.uRmKeyData)
- {
- // 判断是否是连击
- if (uRmKeyBusData_Temp == s_tRmKeyRunData.uRmKeyData)
- {
- // 按键相同 也没有发生过组合 就是连击
- if (s_tRmKeyRunData.uRmKeyDataCnt == Ones8(s_tRmKeyRunData.uRmKeyData))
- {
- s_tRmKeyRunData.uClickCnt++;
- s_u2CombLongFlag |= RM_KEY_MASK_DOBLE; // 连击
- // 复位定时器
- s_tRmKeyRunData.uCombCnt = 0;
- // 更新记录 连击次数
- s_u2CombLongFlag &= 0xF8FF;
- s_u2CombLongFlag |= (s_tRmKeyRunData.uClickCnt << 8) & 0x0700;
-
- if (s_RM_KEY_CFG.uClickCtr <= s_tRmKeyRunData.uClickCnt) // 判断连击门限值
- {
- RM_KEY_PutKeyMsg((u16)s_tRmKeyRunData.uRmKeyData | s_u2CombLongFlag | RM_KEY_MASK_SHORT_D);
- s_tRmKeyRunData.nGobleState = RM_KEY_STATE_WAIT_LONG;
- }
- }
- }
- else // 非法的重复按键发生
- {
- // 单击/连击 按下,组合也是单击
- RM_KEY_PutKeyMsg((u16)s_tRmKeyRunData.uRmKeyData | s_u2CombLongFlag | RM_KEY_MASK_SHORT_D);
-
- s_tRmKeyRunData.nGobleState = RM_KEY_STATE_WAIT_IDLE;
- s_tRmKeyRunData.uIdleCnt = s_RM_KEY_CFG.uIdleCtr;
- }
- }
- else // 没有新的按键按下 或者有新的 但是不是重复的按键按下
- {
- if (uRmKeyBusData_Temp) // 有按键按下
- {
- // 有新的按键按下 但是没有发生过连击 那就是组合
- if (1 == s_tRmKeyRunData.uClickCnt)
- {
- // 更新新加入的按键
- s_u2CombLongFlag |= RM_KEY_MASK_ADD; // 标志是否发生过组合
- s_tRmKeyRunData.uRmKeyData |= s_RM_KEY_CFG.uRmKeyBusData;
- }
- else // 发生过连击
- {
- // 单击/连击 按下,组合也是单击
- RM_KEY_PutKeyMsg((u16)s_tRmKeyRunData.uRmKeyData | s_u2CombLongFlag | RM_KEY_MASK_SHORT_D);
-
- s_tRmKeyRunData.nGobleState = RM_KEY_STATE_WAIT_IDLE;
- s_tRmKeyRunData.uIdleCnt = s_RM_KEY_CFG.uIdleCtr;
- }
- }
- }
- }
- }
- break;
-
- case RM_KEY_STATE_WAIT_LONG:
- {
- // 按键数据保持不变
- if ((s_tRmKeyRunData.uRmKeyData == s_RM_KEY_CFG.uRmKeyBusData) && (0 < s_RM_KEY_CFG.uLongCtr))
- {
- // 可以加上COMB等待的时间 否则时间过长!!!!!!!
- // 支持长按 长按消息只发一次
- if (s_RM_KEY_CFG.uLongCtr > s_tRmKeyRunData.uLongCnt)
- {
- if (s_RM_KEY_CFG.uLongCtr <= (++s_tRmKeyRunData.uLongCnt))
- {
- // 长发消息
- s_u2CombLongFlag |= RM_KEY_MASK_LONG;
- RM_KEY_PutKeyMsg((u16)s_tRmKeyRunData.uRmKeyData | s_u2CombLongFlag | RM_KEY_MASK_SHORT_D);
- }
-
- }
- // 支持连发
- else if (0 < s_RM_KEY_CFG.uRepeatCtr)
- {
- if (s_RM_KEY_CFG.uRepeatCtr <= (++s_tRmKeyRunData.uRepeatCnt))
- {
- s_tRmKeyRunData.uRepeatCnt = 0;
- // 连发消息
- s_u2CombLongFlag |= RM_KEY_MASK_LONG_P;
- // 长发连发
- RM_KEY_PutKeyMsg((u16)s_tRmKeyRunData.uRmKeyData | s_u2CombLongFlag | RM_KEY_MASK_SHORT_D);
- }
- }
- }
- else
- {
- s_tRmKeyRunData.nGobleState = RM_KEY_STATE_WAIT_IDLE;
- s_tRmKeyRunData.uIdleCnt = s_RM_KEY_CFG.uIdleCtr;
- }
- }
- break;
-
- // 延时一段时间 然后进入IDLE
- case RM_KEY_STATE_WAIT_IDLE:
- {
- // 延时后直接进入IDLE模式
- if (s_RM_KEY_CFG.uIdleCtr)
- {
- if (0 < s_tRmKeyRunData.uIdleCnt)
- {
- s_tRmKeyRunData.uIdleCnt--;
-
- // 没有按键也进入空闲模式
- if (0 == s_RM_KEY_CFG.uRmKeyBusData)
- {
- s_tRmKeyRunData.nGobleState = RM_KEY_STATE_IDLE;
- // 单击/连击 弹起,组合也是单击
- RM_KEY_PutKeyMsg((u16)s_tRmKeyRunData.uRmKeyData | s_u2CombLongFlag);
- }
- }
- else
- {
- s_tRmKeyRunData.nGobleState = RM_KEY_STATE_IDLE;
- // 单击/连击 弹起,组合也是单击
- RM_KEY_PutKeyMsg((u16)s_tRmKeyRunData.uRmKeyData | s_u2CombLongFlag);
- }
- }
- else // 必须所有按键都弹开之后才能进入IDLE模式
- {
- if (0 == s_RM_KEY_CFG.uRmKeyBusData)
- {
- s_tRmKeyRunData.nGobleState = RM_KEY_STATE_IDLE;
- // 单击/连击 弹起,组合也是单击
- RM_KEY_PutKeyMsg((u16)s_tRmKeyRunData.uRmKeyData | s_u2CombLongFlag);
- }
- }
- }
- break;
- default:
- break;
-
- }
- // 记录当前按键状态值
- s_uRmKeyBusData_Last = s_RM_KEY_CFG.uRmKeyBusData;
-
- }
- /**
- * @brief 按键扫描函数 10ms调用一次
- *
- * @param [in] 无
- *
- * @return 无
- * @author
- * @since trunk.00001
- * @bug
- */
- void RM_KEY_Scan10ms(void)
- {
- // 更新一次各个按键状态
- RM_KEY_Update();
- RM_KEY_Detect();
- // if (s_KeyTimeOutCount > 0)
- // {
- // if (--s_KeyTimeOutCount == 0)
- // {
- //// LCD_SetBackLight(0); /* 关闭背光 */
- //// LCD_DispOff();
- //// s_LcdOn = 0; /* 屏幕关闭 */
- // }
- // }
- }
- /**
- * @brief 按键初始化函数
- *
- * @param [in] 无
- *
- * @return 无
- * @author
- * @since trunk.00001
- * @bug
- */
- void RM_KEY_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitTypeDefStr;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE); // 使能A、C口时钟
- // Power:PA0 按键初始化,下拉输入
- GPIO_InitTypeDefStr.GPIO_Pin = RM_GPIO_KEY_P_PIN;
- GPIO_InitTypeDefStr.GPIO_Mode = GPIO_Mode_IPD;
- GPIO_Init(RM_GPIO_KEY_P, &GPIO_InitTypeDefStr);
- // A:PA4 按键初始化,下拉输入
- GPIO_InitTypeDefStr.GPIO_Pin = RM_GPIO_KEY_A_PIN;
- GPIO_InitTypeDefStr.GPIO_Mode = GPIO_Mode_IPD;
- GPIO_Init(RM_GPIO_KEY_A, &GPIO_InitTypeDefStr);
- // B:PC0 按键初始化,下拉输入
- GPIO_InitTypeDefStr.GPIO_Pin = RM_GPIO_KEY_B_PIN;
- GPIO_InitTypeDefStr.GPIO_Mode = GPIO_Mode_IPD;
- GPIO_Init(RM_GPIO_KEY_B, &GPIO_InitTypeDefStr);
- // C:PC15 按键初始化,下拉输入
- GPIO_InitTypeDefStr.GPIO_Pin = RM_GPIO_KEY_C_PIN;
- GPIO_InitTypeDefStr.GPIO_Mode = GPIO_Mode_IPD;
- GPIO_Init(RM_GPIO_KEY_C, &GPIO_InitTypeDefStr);
- // D:PC5 按键初始化,下拉输入
- GPIO_InitTypeDefStr.GPIO_Pin = RM_GPIO_KEY_D_PIN;
- GPIO_InitTypeDefStr.GPIO_Mode = GPIO_Mode_IPD;
- GPIO_Init(RM_GPIO_KEY_D, &GPIO_InitTypeDefStr);
-
- // OK:PC14 按键初始化,下拉输入
- GPIO_InitTypeDefStr.GPIO_Pin = RM_GPIO_KEY_O_PIN;
- GPIO_InitTypeDefStr.GPIO_Mode = GPIO_Mode_IPD;
- GPIO_Init(RM_GPIO_KEY_O, &GPIO_InitTypeDefStr);
- // 初始化按键参数
- RM_KEY_SetKeyParamDefault();
-
- }
- <div class="blockcode"><blockquote>#ifndef _RM_KEY_H_
- #define _RM_KEY_H_
- /*******************************************************************************
- * Copyright (C), 1993-2012, Liming Comm. Co., Ltd.
- * @file :RM_KEY.h
- * @brief :Enter the brief description of this file
- * @author :czm_hyt@163.com
- * @version :V1.0
- * @date :2019-11-15
- * @time :20:21:49
- *
- ******************************************************************************
- * 函数列表
- *
- * 1. Enter the name of the first function
- * 2. Enter the name of the second function
- ******************************************************************************
- * 修改历史
- *
- * 2019-11-15 czm 建立文件
- *******************************************************************************/
- #include "RM_GPIO_DEFS.h"
- // 按键滤波检测时间 按下或者弹起都滤波 单位ms
- #define RM_KEY_FILTER_TIME ((u8)3) // 按键滤波时间,总线稳定后,持续的时间 可以短一些 影响多键的判断
- #define RM_KEY_COMB_TIME ((u8)25) // 组合按键或者连击等待时间 影响到组合
- #define RM_KEY_LONG_TIME ((u8)80) // 按键长按判断 1秒钟算长按 可以包含COMB也可以不包含
- #define RM_KEY_REPEAT_TIME ((u8)10) // 长按后连续触发按键的周期
- #define RM_KEY_IDLE_TIME ((u8)25) // 按键弹开后,如何进入IDLE模式,0:必须没有按键才能进入,其它:延时对应时间,强制进IDLE
- #define RM_KEY_CLICK_CTR ((u8)7) // 最多支持多少连击 最小值是2 最大值7,3个bit计数,支持组合时生效,否则不生效
-
- #define RM_HARD_KEY_NUM ((u8)6) // RM 硬件按键个数
- #define RM_KEY_MSG_FIFO_SIZE ((u8)10) // 用来存储按键码的缓存FIFO大小
- /**
- * @enum RM_KEY_ID_E
- * @brief 按键的ID号
- */
- typedef enum _RM_KEY_ID_E
- {
- RM_KEY_ID_A = 0x00, ///< 按键 A
- RM_KEY_ID_B, ///< 按键 B
- RM_KEY_ID_C, ///< 按键 C
- RM_KEY_ID_D, ///< 按键 D
- RM_KEY_ID_O, ///< 按键 OK
- RM_KEY_ID_P ///< 按键 Power
-
- } RM_KEY_ID_E;
- /**
- * @enum RM_KEY_STATE_E
- * @brief 按键状态
- */
- typedef enum _RM_KEY_STATE_E
- {
- RM_KEY_STATE_IDLE = 0x00, ///< 常态 空闲
- RM_KEY_STATE_WAIT_COMB, ///< 过度状态 开始等待组合或者多击,弹开时也会用到这个状态,用来判断两次按键按下的间隔
- RM_KEY_STATE_WAIT_LONG, ///< 等待进入长按状态 或者不支持长按
- RM_KEY_STATE_WAIT_IDLE ///< 等待空闲状态,按键不松开,长期挺溜此状态
-
- } RM_KEY_STATE_E;
- /**
- * @brief 按键GPIO定义的结构体 需要设置按键有效的电平是高还是低
- */
- typedef struct _RM_KEY_GPIO_DEF_T
- {
- GPIO_TypeDef* ptGpio; // GPIO 端口
- u16 u2Pin; // GPIO 管脚
- BOOL bActiveLevel; // 按键有效激活电平
-
- } RM_KEY_GPIO_DEF_T;
- /**
- * @brief RM 逻辑按键参数配置
- */
- typedef struct _RM_KEY_LOGIC_CONFIG_T
- {
- u8 uRmKeyBusData; // 按键总线数据 10ms更新一次 带滤波
- u8 uKeyBusDataCnt; // 当前有效按键的个数
-
- // 滤波是指按键按下,去掉抖动之后,平稳的时间达到阈值才生效
- u8 uFilterCtr; // 按键底层总线滤波,按键接近时,可滤波成同时按下,既多键
-
- u8 uCombCtr; // 组合、连击等待时间阈值 0 表示不支持,最大2.5s
- u8 uClickCtr; // 连击最大次数,必须支持组合/连击时才生效 最小值2 最大值7
-
- u8 uLongCtr; // 长按计数器 等待阈值 0 表示不支持,最大2.5s
- u8 uRepeatCtr ; // 长按连续发送阈值, 0 表示不支持,最大2.5s,必须支持长按时才生效
-
- u8 uIdleCtr; // 按键弹开后,如何进入IDLE模式,0:必须没有按键才能进入,其它:延时对应时间,强制进IDLE
-
- } RM_KEY_CONFIG_T;
- /**
- * @brief 逻辑按键计数器
- */
- typedef struct _RM_KEY_RUN_DATA_T
- {
- RM_KEY_STATE_E nGobleState; // 按键处理状态机状态
-
- u8 uRmKeyData; // 有效的按键数据
- u8 uRmKeyDataCnt; // 有效按键个数
- u8 uFIlterCount; // 逻辑滤波计数器 单位毫秒 等于物理按键的滤波时间
-
- u8 uCombCnt; // 组合按键或者多击计数器
- u8 uClickCnt; // 按键单击次数
-
- u8 uLongCnt; // 长按计数器
- u8 uRepeatCnt; // 长按连续发送计数器
-
- u8 uIdleCnt; // 长按连续发送计数器
- // 消息缓存区设置
- // b15:长按/短按;b14:连发;b13:是否发生过组合;b10~b8:连击次数;
- // b7:按下/弹开;b6:连击/单击; b5~b0:按键
- u16 u2MsgBuf[RM_KEY_MSG_FIFO_SIZE]; // 按键消息缓存区
- u8 uWriteAddr; // 缓冲区写指针
- u8 uReadAddrA; // 缓冲区读指针1
- u8 uReadAddrB; // 缓冲区读指针2,不同的函数同时读取缓存区
-
- } RM_KEY_RUN_DATA_T;
- // 按键按下或者弹开 后面两个选项可以用来修饰按键的具体情况
- #define RM_KEY_MASK_SHORT_D ((u16)0x0080) // 按键按下
- #define RM_KEY_MASK_SHORT_U ((u16)0x0000) // 按键弹开
- // 按键类型
- #define RM_KEY_MASK_DOBLE ((u16)0x0040) // 连击
- #define RM_KEY_MASK_ADD ((u16)0x2000) // 发生了组合
- // 两个同时只能用一个 支持连发时 不会生产长按弹起 而是长按连发弹起!!!
- #define RM_KEY_MASK_LONG ((u16)0x8000) // 长按
- #define RM_KEY_MASK_LONG_P ((u16)0xC000) // 连发 一定长按
- #define RM_KEY_BIT_DEF_A ((u16)0x0001)
- #define RM_KEY_BIT_DEF_B ((u16)0x0002)
- #define RM_KEY_BIT_DEF_C ((u16)0x0004)
- #define RM_KEY_BIT_DEF_D ((u16)0x0008)
- #define RM_KEY_BIT_DEF_O ((u16)0x0010)
- #define RM_KEY_BIT_DEF_P ((u16)0x0020)
- #define RM_KEY_BIT_DEF_ALL ((u16)0x003F)
- #define RM_KEY_MASK_DU (RM_KEY_MASK_SHORT_D |RM_KEY_BIT_DEF_ALL) // 不区分 单击/连击 不区分 长按/连发
- #define RM_KEY_MASK_DU_C (RM_KEY_MASK_DU |RM_KEY_MASK_DOBLE) // 区分 单击/连击 不区分长按/连发
- #define RM_KEY_MASK_DU_L (RM_KEY_MASK_DU |RM_KEY_MASK_LONG) // 不区分 单击/连击 区分 长按
- #define RM_KEY_MASK_DU_LP (RM_KEY_MASK_DU |RM_KEY_MASK_LONG_P) // 不区分 单击/连击 区分 长按/连发
- // 支持连发的时候,连发结束后,有连发弹起,没有长按弹起
- #define RM_KEY_MASK_DU_CL (RM_KEY_MASK_DU_C |RM_KEY_MASK_LONG) // 区分 单击/连击 区分 长按
- #define RM_KEY_MASK_DU_CLP (RM_KEY_MASK_DU_C |RM_KEY_MASK_LONG_P) // 区分 单击/连击 区分 长按/连发
-
- // 按键 A
- #define RM_MSG_KEY_A_SD (RM_KEY_BIT_DEF_A | RM_KEY_MASK_SHORT_D) // 单键 短按按下
- #define RM_MSG_KEY_A_SU (RM_KEY_BIT_DEF_A | RM_KEY_MASK_SHORT_U) // 单键 短按弹起
- #define RM_MSG_KEY_A_C_SD (RM_MSG_KEY_A_SD | RM_KEY_MASK_DOBLE) // 组合或者双击等 短按按下 最后一次按键是短按
- #define RM_MSG_KEY_A_C_SU (RM_MSG_KEY_A_SU | RM_KEY_MASK_DOBLE) // 组合或者双击等 短按弹起 最后一次按键是短按
- // 按键 B
- #define RM_MSG_KEY_B_SD (RM_KEY_BIT_DEF_B | RM_KEY_MASK_SHORT_D) // 单键 短按按下
- #define RM_MSG_KEY_B_SU (RM_KEY_BIT_DEF_B | RM_KEY_MASK_SHORT_U) // 单键 短按弹起
- #define RM_MSG_KEY_B_C_SD (RM_MSG_KEY_B_SD | RM_KEY_MASK_DOBLE) // 组合或者双击等 短按按下 最后一次按键是短按
- #define RM_MSG_KEY_B_C_SU (RM_MSG_KEY_B_SU | RM_KEY_MASK_DOBLE) // 组合或者双击等 短按弹起 最后一次按键是短按
- // 按键 C
- #define RM_MSG_KEY_C_SD (RM_KEY_BIT_DEF_C | RM_KEY_MASK_SHORT_D) // 单键 短按按下
- #define RM_MSG_KEY_C_SU (RM_KEY_BIT_DEF_C | RM_KEY_MASK_SHORT_U) // 单键 短按弹起
- #define RM_MSG_KEY_C_C_SD (RM_MSG_KEY_C_SD | RM_KEY_MASK_DOBLE) // 组合或者双击等 短按按下 最后一次按键是短按
- #define RM_MSG_KEY_C_C_SU (RM_MSG_KEY_C_SU | RM_KEY_MASK_DOBLE) // 组合或者双击等 短按弹起 最后一次按键是短按
- // 按键 D
- #define RM_MSG_KEY_D_SD (RM_KEY_BIT_DEF_D | RM_KEY_MASK_SHORT_D) // 单键 短按按下
- #define RM_MSG_KEY_D_SU (RM_KEY_BIT_DEF_D | RM_KEY_MASK_SHORT_U) // 单键 短按弹起
- #define RM_MSG_KEY_D_C_SD (RM_MSG_KEY_D_SD | RM_KEY_MASK_DOBLE) // 组合或者双击等 短按按下 最后一次按键是短按
- #define RM_MSG_KEY_D_C_SU (RM_MSG_KEY_D_SU | RM_KEY_MASK_DOBLE) // 组合或者双击等 短按弹起 最后一次按键是短按
- // 按键 O
- #define RM_MSG_KEY_O_SD (RM_KEY_BIT_DEF_O | RM_KEY_MASK_SHORT_D) // 单键 短按按下
- #define RM_MSG_KEY_O_SU (RM_KEY_BIT_DEF_O | RM_KEY_MASK_SHORT_U) // 单键 短按弹起
- #define RM_MSG_KEY_O_C_SD (RM_MSG_KEY_O_SD | RM_KEY_MASK_DOBLE) // 组合或者双击等 短按按下 最后一次按键是短按
- #define RM_MSG_KEY_O_C_SU (RM_MSG_KEY_O_SU | RM_KEY_MASK_DOBLE) // 组合或者双击等 短按弹起 最后一次按键是短按
- // 按键 P
- #define RM_MSG_KEY_P_SD (RM_KEY_BIT_DEF_P | RM_KEY_MASK_SHORT_D) // 单键 短按按下
- #define RM_MSG_KEY_P_SU (RM_KEY_BIT_DEF_P | RM_KEY_MASK_SHORT_U) // 单键 短按弹起
- #define RM_MSG_KEY_P_C_SD (RM_MSG_KEY_P_SD | RM_KEY_MASK_DOBLE) // 组合或者双击等 短按按下 最后一次按键是短按
- #define RM_MSG_KEY_P_C_SU (RM_MSG_KEY_P_SU | RM_KEY_MASK_DOBLE) // 组合或者双击等 短按弹起 最后一次按键是短按
- // 按键 AB
- #define RM_MSG_KEY_AB_SD (RM_KEY_BIT_DEF_A | RM_MSG_KEY_B_SD)
- #define RM_MSG_KEY_AB_SU (RM_KEY_BIT_DEF_A | RM_MSG_KEY_B_SU)
- #define RM_MSG_KEY_AB_C_SD (RM_KEY_BIT_DEF_A | RM_MSG_KEY_B_C_SD)
- #define RM_MSG_KEY_AB_C_SU (RM_KEY_BIT_DEF_A | RM_MSG_KEY_B_C_SU)
- // 按键 AC
- #define RM_MSG_KEY_AC_SD (RM_KEY_BIT_DEF_A | RM_MSG_KEY_C_SD)
- #define RM_MSG_KEY_AC_SU (RM_KEY_BIT_DEF_A | RM_MSG_KEY_C_SU)
- #define RM_MSG_KEY_AC_C_SD (RM_KEY_BIT_DEF_A | RM_MSG_KEY_C_C_SD)
- #define RM_MSG_KEY_AC_C_SU (RM_KEY_BIT_DEF_A | RM_MSG_KEY_C_C_SU)
- // 按键 AD
- #define RM_MSG_KEY_AD_SD (RM_KEY_BIT_DEF_A | RM_MSG_KEY_D_SD)
- #define RM_MSG_KEY_AD_SU (RM_KEY_BIT_DEF_A | RM_MSG_KEY_D_SU)
- #define RM_MSG_KEY_AD_C_SD (RM_KEY_BIT_DEF_A | RM_MSG_KEY_D_C_SD)
- #define RM_MSG_KEY_AD_C_SU (RM_KEY_BIT_DEF_A | RM_MSG_KEY_D_C_SU)
- // 按键 AO
- #define RM_MSG_KEY_AO_SD (RM_KEY_BIT_DEF_A | RM_MSG_KEY_O_SD)
- #define RM_MSG_KEY_AO_SU (RM_KEY_BIT_DEF_A | RM_MSG_KEY_O_SU)
- #define RM_MSG_KEY_AO_C_SD (RM_KEY_BIT_DEF_A | RM_MSG_KEY_O_C_SD)
- #define RM_MSG_KEY_AO_C_SU (RM_KEY_BIT_DEF_A | RM_MSG_KEY_O_C_SU)
- // 按键 AP
- #define RM_MSG_KEY_AP_SD (RM_KEY_BIT_DEF_A | RM_MSG_KEY_P_SD)
- #define RM_MSG_KEY_AP_SU (RM_KEY_BIT_DEF_A | RM_MSG_KEY_P_SU)
- #define RM_MSG_KEY_AP_C_SD (RM_KEY_BIT_DEF_A | RM_MSG_KEY_P_C_SD)
- #define RM_MSG_KEY_AP_C_SU (RM_KEY_BIT_DEF_A | RM_MSG_KEY_P_C_SU)
- // 按键 BC
- #define RM_MSG_KEY_BC_SD (RM_KEY_BIT_DEF_B | RM_MSG_KEY_C_SD)
- #define RM_MSG_KEY_BC_SU (RM_KEY_BIT_DEF_B | RM_MSG_KEY_C_SU)
- #define RM_MSG_KEY_BC_C_SD (RM_KEY_BIT_DEF_B | RM_MSG_KEY_C_C_SD)
- #define RM_MSG_KEY_BC_C_SU (RM_KEY_BIT_DEF_B | RM_MSG_KEY_C_C_SU)
- // 按键 BD
- #define RM_MSG_KEY_BD_SD (RM_KEY_BIT_DEF_B | RM_MSG_KEY_D_SD)
- #define RM_MSG_KEY_BD_SU (RM_KEY_BIT_DEF_B | RM_MSG_KEY_D_SU)
- #define RM_MSG_KEY_BD_C_SD (RM_KEY_BIT_DEF_B | RM_MSG_KEY_D_C_SD)
- #define RM_MSG_KEY_BD_C_SU (RM_KEY_BIT_DEF_B | RM_MSG_KEY_D_C_SU)
- // 按键 BO
- #define RM_MSG_KEY_BO_SD (RM_KEY_BIT_DEF_B | RM_MSG_KEY_O_SD)
- #define RM_MSG_KEY_BO_SU (RM_KEY_BIT_DEF_B | RM_MSG_KEY_O_SU)
- #define RM_MSG_KEY_BO_C_SD (RM_KEY_BIT_DEF_B | RM_MSG_KEY_O_C_SD)
- #define RM_MSG_KEY_BO_C_SU (RM_KEY_BIT_DEF_B | RM_MSG_KEY_O_C_SU)
- // 按键 BP
- #define RM_MSG_KEY_BP_SD (RM_KEY_BIT_DEF_B | RM_MSG_KEY_P_SD)
- #define RM_MSG_KEY_BP_SU (RM_KEY_BIT_DEF_B | RM_MSG_KEY_P_SU)
- #define RM_MSG_KEY_BP_C_SD (RM_KEY_BIT_DEF_B | RM_MSG_KEY_P_C_SD)
- #define RM_MSG_KEY_BP_C_SU (RM_KEY_BIT_DEF_B | RM_MSG_KEY_P_C_SU)
- // 按键 CD
- #define RM_MSG_KEY_CD_SD (RM_KEY_BIT_DEF_C | RM_MSG_KEY_D_SD)
- #define RM_MSG_KEY_CD_SU (RM_KEY_BIT_DEF_C | RM_MSG_KEY_D_SU)
- #define RM_MSG_KEY_CD_C_SD (RM_KEY_BIT_DEF_C | RM_MSG_KEY_D_C_SD)
- #define RM_MSG_KEY_CD_C_SU (RM_KEY_BIT_DEF_C | RM_MSG_KEY_D_C_SU)
- // 按键 CO
- #define RM_MSG_KEY_CO_SD (RM_KEY_BIT_DEF_C | RM_MSG_KEY_O_SD)
- #define RM_MSG_KEY_CO_SU (RM_KEY_BIT_DEF_C | RM_MSG_KEY_O_SU)
- #define RM_MSG_KEY_CO_C_SD (RM_KEY_BIT_DEF_C | RM_MSG_KEY_O_C_SD)
- #define RM_MSG_KEY_CO_C_SU (RM_KEY_BIT_DEF_C | RM_MSG_KEY_O_C_SU)
- // 按键 CP
- #define RM_MSG_KEY_CP_SD (RM_KEY_BIT_DEF_C | RM_MSG_KEY_P_SD)
- #define RM_MSG_KEY_CP_SU (RM_KEY_BIT_DEF_C | RM_MSG_KEY_P_SU)
- #define RM_MSG_KEY_CP_C_SD (RM_KEY_BIT_DEF_C | RM_MSG_KEY_P_C_SD)
- #define RM_MSG_KEY_CP_C_SU (RM_KEY_BIT_DEF_C | RM_MSG_KEY_P_C_SU)
- // 按键 DO
- #define RM_MSG_KEY_DO_SD (RM_KEY_BIT_DEF_D | RM_MSG_KEY_O_SD)
- #define RM_MSG_KEY_DO_SU (RM_KEY_BIT_DEF_D | RM_MSG_KEY_O_SU)
- #define RM_MSG_KEY_DO_C_SD (RM_KEY_BIT_DEF_D | RM_MSG_KEY_O_C_SD)
- #define RM_MSG_KEY_DO_C_SU (RM_KEY_BIT_DEF_D | RM_MSG_KEY_O_C_SU)
- // 按键 DP
- #define RM_MSG_KEY_DP_SD (RM_KEY_BIT_DEF_D | RM_MSG_KEY_P_SD)
- #define RM_MSG_KEY_DP_SU (RM_KEY_BIT_DEF_D | RM_MSG_KEY_P_SU)
- #define RM_MSG_KEY_DP_C_SD (RM_KEY_BIT_DEF_D | RM_MSG_KEY_P_C_SD)
- #define RM_MSG_KEY_DP_C_SU (RM_KEY_BIT_DEF_D | RM_MSG_KEY_P_C_SU)
- // 按键 OP
- #define RM_MSG_KEY_OP_SD (RM_KEY_BIT_DEF_O | RM_MSG_KEY_P_SD)
- #define RM_MSG_KEY_OP_SU (RM_KEY_BIT_DEF_O | RM_MSG_KEY_P_SU)
- #define RM_MSG_KEY_OP_C_SD (RM_KEY_BIT_DEF_O | RM_MSG_KEY_P_C_SD)
- #define RM_MSG_KEY_OP_C_SU (RM_KEY_BIT_DEF_O | RM_MSG_KEY_P_C_SU)
- extern u8 RM_KEY_GetKeyState(void);
- extern void RM_KEY_Init(void);
- extern void RM_KEY_Scan10ms(void);
- extern void RM_KEY_PutKeyMsg(u16 u2KeyMsgCode);
- extern u16 RM_KEY_GetKeyMsgA(void);
- extern void RM_KEY_SetKeyParam(u8 uFilterCtr, u8 uCombCtr, u8 uClickCtr, u8 uLongCtr, u8 uRepeatCtr, u8 uIdleCtr);
- #endif /* _RM_KEY_H_ */
复制代码
|
|