├── .gitignore ├── README.md ├── key.c └── key.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # key: 一个精简但功能强大的按键驱动 2 | 3 | ![version](https://img.shields.io/badge/version-0.7-brightgreen.svg) 4 | ![build](https://img.shields.io/badge/build-2019.4.26-brightgreen.svg) 5 | ![build](https://img.shields.io/badge/license-MIT-brightgreen.svg) 6 | 7 | ## 1. 介绍 8 | 9 | 这是一个通过位操作实现状态机转换的按键驱动,通过独特的算法,在非常非常小的资源消耗下实现短按键/shift键/长按连发,长按单发等多种复杂的按键功能。 10 | 11 | ## 2. 原理介绍 12 | 13 | ### 2.1 键值码 14 | - 本按键驱动键值码的方式返回按键输入状态,键值码中每一个位表示一个按键。 15 | - 键值码根据配置长度从8位到~64位(即最多支持64个按键)。 16 | - 键值码根据实际情况分成短按键值码shift键值码,长按键值码 17 | ``` 18 | 短按键值码 = 键值码 19 | shift键值码 = shift键值码 | 键值码. 20 | 长按键值码 = ~键值码 21 | ``` 22 | 23 | ### 3.算法说明 24 | 25 | ``` 26 | //PreKey:前次按键值 27 | //NowKey:当前按键值 28 | //PreScanKey:前次采样值 29 | //NowReadKey:当前采样值 30 | a.按键获取算法 31 | 1).NowKey & PreKey : 电平触发 32 | 2).NowKey ^ PreKey : 边缘触发 33 | 3).NowKey & (NowKey ^ PreKey)或(~PreKey) & NowKey : 上升沿触发 34 | 4).PreKey & (NowKey ^ PreKey)或PreKey & (~NowKey) : 下降沿触发 35 | b.滤波算法 36 | 1).PreScanKey & NowScanKey : 电平触发 37 | 2).PreReadKey & (PreScanKey ^ NowScanKey) : 采样保持 38 | 3).NowReadKey = 1) | 2) : 带采样保持的电平触发 39 | //以上算法可通过列真值表推导 40 | ``` 41 | 42 | ## 4.功能说明 43 | 44 | - 支持最大64个按键(数量可配置)。 45 | - 支持按键消抖处理(可滤掉小于2个扫描周期的毛刺)。 46 | - 支持按键环形缓冲区(长度可配置)。 47 | - 支持4种不同按键模式:A:短按键 B:shift键 C:长按单发 D:长按连发。 48 | - 短按键 :短按直接输出键值。 49 | - shift键 :点击后除了输出一次shift键的键值码外,还将后续所有其他按键的键值改为shift键值码 50 | - 长按连发 :长按一定时间后连续输出按键键值。 51 | - 长按单发 :长按一定时间后反码输出键值(仅一次) 52 | - 4种不同按键模式可相互叠加使用,所有按键功能都能并发输出。 53 | 54 | ## 5. 移植说明 55 | 56 | - 使用宏或枚举定义按键键值码。(长按单发使用反码表示) 57 | ``` 58 | typedef enum 59 | { 60 | //短按键键值码 61 | KEY_UP = 0x0001, 62 | KEY_DN = 0x0002, 63 | KEY_LT = 0x0004, 64 | KEY_RT = 0x0008, 65 | KEY_ENT = 0x0010, 66 | KEY_ESC = 0x0020, 67 | KEY_INC = 0x0040, 68 | KEY_DEC = 0x0080, 69 | KEY_FUN = 0x0100, 70 | //长按键键值码 71 | KEY_UP_L = 0xFFFE, 72 | KEY_DN_L = 0xFFFD, 73 | //shift按键键值码 74 | KEY_UP_SF = 0x0101, 75 | KEY_DN_SF = 0x0102, 76 | KEY_LT_SF = 0x0104, 77 | KEY_RT_SF = 0x0108, 78 | KEY_ENT_SF = 0x0110, 79 | KEY_ESC_SF = 0x0120, 80 | KEY_INC_SF = 0x0140, 81 | KEY_DEC_SF = 0x0180 82 | } KEY_value; 83 | ``` 84 | - 根据具体硬件环境编写按键初始化函数KeyInit()。 85 | - 根据编写按键读取函数KeyIOread(),注意所有按键均需定义为高电平有效。 86 | 87 | ``` 88 | __weak static KEY_TYPE KeyIOread( void ) 89 | { 90 | KEY_TYPE KeyScanCode=0; 91 | 92 | KeyScanCode |= GPIO_IN(K_UP ) ? 0 : KEY_UP ; 93 | KeyScanCode |= GPIO_IN(K_DN ) ? 0 : KEY_DN ; 94 | KeyScanCode |= GPIO_IN(K_LT ) ? 0 : KEY_LT ; 95 | KeyScanCode |= GPIO_IN(K_RT ) ? 0 : KEY_RT ; 96 | KeyScanCode |= GPIO_IN(K_ENT) ? 0 : KEY_ENT; 97 | KeyScanCode |= GPIO_IN(K_ESC) ? 0 : KEY_ESC; 98 | KeyScanCode |= GPIO_IN(K_INC) ? 0 : KEY_INC; 99 | KeyScanCode |= GPIO_IN(K_DEC) ? 0 : KEY_DEC; 100 | KeyScanCode |= GPIO_IN(K_FUN) ? 0 : KEY_FUN; 101 | 102 | return KeyScanCode; 103 | } 104 | ``` 105 | 106 | ## 6. 使用说明 107 | 108 | - 按需求配置宏 109 | 110 | | 宏 | 意义 | 111 | | ----------------------------- | -------------------------------------------------------- | 112 | | KEY_MAX_NUM | 定义最大按键数量(1~64) | 113 | | KEY_BUF_SIZE | 定义按键缓冲区大小(2,4,8,16,32,64,128,256) | 114 | | KEY_LONG_EN | 定义是否支持长按键(1 or 0) | 115 | | KEY_SHORT_SHIFT | 定义shift键,短按有效(0 or 按键键值码) | 116 | | KEY_PRESS_DLY | 定义长按键延时n个扫描周期开始判定有效值(1~255) | 117 | | KEY_PRESS_TMR | 定义长按键n个扫描周期为1次有效扫描值(1~255) | 118 | | KEY_LONG_SHIFT | 长按键反码输出(仅一次),未定义的长按连续输出(0 or 按键键值码) | 119 | 120 | - 每20ms~50ms调用KeyScan()扫描按键。 121 | - 调用KeyGetBufLen()判断是否有按键,调用KeyGet()获得按键值。 122 | 123 | ``` 124 | void KeyTest(void) 125 | { 126 | while(1) 127 | { 128 | 129 | KeyScan(); 130 | delay_ms(20); 131 | KeyScan(); 132 | 133 | switch(KeyGet()) 134 | { 135 | case KEY_UP : printf("Key Read : UP \r\n");break; 136 | case KEY_DN : printf("Key Read : DN \r\n");break; 137 | case KEY_LT : printf("Key Read : LT \r\n");break; 138 | case KEY_RT : printf("Key Read : RT \r\n");break; 139 | case KEY_ENT: printf("Key Read : ENT\r\n");break; 140 | case KEY_ESC: printf("Key Read : ESC\r\n");break; 141 | case KEY_INC: printf("Key Read : INC\r\n");break; 142 | case KEY_DEC: printf("Key Read : DEC\r\n");break; 143 | case KEY_FUN: printf("Key Read : FUN\r\n");break; 144 | case KEY_UP_L : printf("Key Read : UP for long key \r\n");break; 145 | case KEY_DN_L : printf("Key Read : DN for long key \r\n");break; 146 | case KEY_UP_SF : printf("Key Read : UP with shift key \r\n");break; 147 | case KEY_DN_SF : printf("Key Read : DN with shift key \r\n");break; 148 | case KEY_LT_SF : printf("Key Read : LT with shift key \r\n");break; 149 | case KEY_RT_SF : printf("Key Read : RT with shift key \r\n");break; 150 | case KEY_ENT_SF: printf("Key Read : ENT with shift key \r\n");break; 151 | case KEY_ESC_SF: printf("Key Read : ESC with shift key \r\n");break; 152 | case KEY_INC_SF: printf("Key Read : INC with shift key \r\n");break; 153 | case KEY_DEC_SF: printf("Key Read : DEC with shift key \r\n");break; 154 | default : break; 155 | } 156 | } 157 | 158 | } 159 | ``` 160 | 161 | ## 8. 更新说明 162 | 163 | - V0.1 2011-3-2 164 | 165 | - 1.支持矩阵键盘和IO按键两种 166 | - 2.支持长按键和短按键两种触发方式。 167 | 168 | - V0.2 2011-3-5 169 | 170 | - 1.最大按键数量16个,可继续扩充至64个. 171 | - 2.支持长按键和短按键并行触发. 172 | - 3.增加短按键部分改为按键释放时返回. 173 | 174 | - V0.3 2013-11-4 175 | - 1.重写按键获取的逻辑,长按键算法不成熟,暂时去掉 176 | - 2.矩阵按键没用到,暂时去掉 177 | - 3.增加按键消抖算法 178 | 179 | - V0.4 2013-11-6 180 | - 1.增加环形buf 181 | - 2.重写接口函数,便于在OS环境中调用,当然裸奔也支持. 182 | 183 | - V0.5 2013-11-6 184 | - 1.增加长按键的支持 185 | - 2.增加shift键的支持 186 | - 3.增加按键数量的定义,定义后根据按键数量选择合适的数据类型,从而节省ram和rom 187 | - 4.处于兼容性的考虑,将最大按键支持数量由64个缩减至32个 188 | 189 | - V0.6 2013-11-24 190 | - 1.修正长按键输出后,还输出短按键的bug 191 | - 2.修改的KeyScan()的逻辑,将长按键细分为长按键连续输出和长按键反码输出(仅一次)两种方式 192 | - 3.shift键按下时也提供按键值输出,方便应用程序判断shift键的状态 193 | - 4.由于第3点的修改,短按键和shift键不在冲突,即长按键/短按键/shift键相互独立 194 | - 5.将无按键返回0xff,改成返回0 195 | - 6.增加一个KeyFlush()函数,用于清空buf 196 | 197 | - V0.7 2019-04-26 198 | - 1.参照liunx上kfifo的代码优化环形buf的算法. 199 | - 2.将KeyHit()函数重命名为KeyBufLen()函数,将返回有无按键改为返回按键缓冲数量. 200 | - 3.KEY_TYPE 改为使用stdint.h中的数据类型定义,并重新启用64个按键的支持. 201 | 202 | -------------------------------------------------------------------------------- /key.c: -------------------------------------------------------------------------------- 1 | /** **************************************************************************** 2 | * @file key.c 3 | * @author mojinpan 4 | * @copyright (c) 2018 - 2020 mojinpan 5 | * @brief 按键驱动 6 | * 7 | * @version V0.1 8 | * @date 2011-3-2 9 | * @details 10 | * 1.支持矩阵键盘和IO按键两种 11 | * 2.支持长按键和短按键两种触发方式。 12 | * 13 | * @version V0.2 14 | * @date 2011-3-5 15 | * @details 16 | * 1.最大按键数量16个,可继续扩充至64个. 17 | * 2.支持长按键和短按键并行触发. 18 | * 3.增加短按键部分改为按键释放时返回. 19 | * 20 | * @version V0.3 21 | * @date 2013-11-4 22 | * @details 23 | * 1.重写按键获取的逻辑,长按键算法不成熟,暂时去掉 24 | * 2.矩阵按键没用到,暂时去掉 25 | * 3.增加按键消抖算法 26 | * 27 | * @version V0.4 28 | * @date 2013-11-6 29 | * @details 30 | * 1.增加环形buf 31 | * 2.重写接口函数,便于在OS环境中调用,当然裸奔也支持. 32 | * c_cpp_properties.json 33 | * @version V0.5 34 | * @date 2013-11-6 35 | * @details 36 | * 1.增加长按键的支持 37 | * 2.增加shift键的支持 38 | * 3.增加按键数量的定义,定义后根据按键数量选择合适的数据类型,从而节省ram和rom 39 | * 4.处于兼容性的考虑,将最大按键支持数量由64个缩减至32个 40 | * 41 | * @version V0.6 42 | * @date 2013-11-24 43 | * @details 44 | * 1.修正长按键输出后,还输出短按键的bug 45 | * 2.修改的KeyScan()的逻辑,将长按键细分为长按键连续输出和长按键反码输出(仅一次)两种方式 46 | * 3.shift键按下时也提供按键值输出,方便应用程序判断shift键的状态 47 | * 4.由于第3点的修改,短按键和shift键不在冲突,即长按键/短按键/shift键相互独立 48 | * 5.将无按键返回0xff,改成返回0 49 | * 6.增加一个KeyFlush()函数,用于清空buf 50 | * 51 | * @version V0.7 52 | * @date 2019-04-26 53 | * @details 54 | * 1.参照liunx上kfifo的代码优化环形buf的算法. 55 | * 2.将KeyHit()函数重命名为KeyBufLen()函数,将返回有无按键改为返回按键缓冲数量. 56 | * 3.KEY_TYPE 改为使用stdint.h中的数据类型定义,并重新启用64个按键的支持 57 | *******************************************************************************/ 58 | 59 | #include "bsp.h" 60 | #include "key.h" 61 | 62 | /******************************************************************************* 63 | Macro Definition 宏定义 64 | *******************************************************************************/ 65 | #if KEY_MAX_NUM > 32 66 | #define KEY_TYPE uint64_t 67 | #elif KEY_MAX_NUM > 16 68 | #define KEY_TYPE uint32_t 69 | #elif KEY_MAX_NUM > 8 70 | #define KEY_TYPE uint16_t 71 | #else 72 | #define KEY_TYPE uint8_t 73 | #endif 74 | /******************************************************************************* 75 | Global Variables 全局变量 76 | *******************************************************************************/ 77 | static KEY_TYPE PreScanKey = 0; //前次按键扫描值 78 | static KEY_TYPE PreReadKey = 0; //前次按键读取值 79 | static KEY_TYPE KeyShift = 0; //shift按键记录 80 | static KEY_TYPE KeyMask = 0; //按键掩码 81 | #if LONG_KEY_EN > 0 82 | static uint8_t KeyPressTmr = 0; //长按键判断周期 83 | #endif 84 | 85 | static KEY_TYPE KeyBuf[KEY_BUF_SIZE]; //环形buf 86 | static uint8_t KeyBufInIdx = 0; //buf入指针 87 | static uint8_t KeyBufOutIdx = 0; //buf出指针 88 | /** **************************************************************************** 89 | @brief 按键扫描函数,需根据实际硬件情况进行移植 90 | @note 所有按键均必须高电平有效 91 | *******************************************************************************/ 92 | __weak static KEY_TYPE KeyIOread( void ) 93 | { 94 | KEY_TYPE KeyScanCode=0; 95 | 96 | KeyScanCode |= GPIO_IN(K_UP ) ? 0 : KEY_UP ; 97 | KeyScanCode |= GPIO_IN(K_DN ) ? 0 : KEY_DN ; 98 | KeyScanCode |= GPIO_IN(K_LT ) ? 0 : KEY_LT ; 99 | KeyScanCode |= GPIO_IN(K_RT ) ? 0 : KEY_RT ; 100 | KeyScanCode |= GPIO_IN(K_ENT) ? 0 : KEY_ENT; 101 | KeyScanCode |= GPIO_IN(K_ESC) ? 0 : KEY_ESC; 102 | KeyScanCode |= GPIO_IN(K_INC) ? 0 : KEY_INC; 103 | KeyScanCode |= GPIO_IN(K_DEC) ? 0 : KEY_DEC; 104 | KeyScanCode |= GPIO_IN(K_FUN) ? 0 : KEY_FUN; 105 | 106 | return KeyScanCode; 107 | } 108 | 109 | /** **************************************************************************** 110 | @brief 从buf中获得一个按键值 111 | @return 返回按键值,无按键返回0xFF 112 | *******************************************************************************/ 113 | static KEY_TYPE KeyBufOut (void) 114 | { 115 | if(KeyBufOutIdx == KeyBufInIdx) return 0; //buf空 116 | return KeyBuf[KeyBufOutIdx++ & (KEY_BUF_SIZE- 1)]; //返回按键值 117 | } 118 | /** **************************************************************************** 119 | @brief 将按键值放入buf中 120 | @param code: 需放入buf的按键值 121 | *******************************************************************************/ 122 | static void KeyBufIn (KEY_TYPE code) 123 | { 124 | if(KeyBufInIdx - KeyBufOutIdx == KEY_BUF_SIZE) 125 | { 126 | KeyBufOutIdx++;//buf满则放弃最早的一个按键值 127 | } 128 | 129 | KeyBuf[KeyBufInIdx++ & (KEY_BUF_SIZE- 1)] = code ; 130 | } 131 | 132 | /** **************************************************************************** 133 | @brief 按键扫描 134 | @details 135 | 1.功能说明 136 | a.按键消抖 137 | b.捕捉长按键和短按键 138 | c.根据设置将按键分成短按键/长按连续建/短按shift键/长按shift键4种方式写入buf 139 | 2.算法说明 140 | a.按键获取算法 141 | 1).NowKey & PreKey : 电平触发 142 | 2).NowKey ^ PreKey : 边缘触发 143 | 3).NowKey & (NowKey ^ PreKey)或(~PreKey) & NowKey : 上升沿触发 144 | 4).PreKey & (NowKey ^ PreKey)或PreKey & (~NowKey) : 下降沿触发 145 | b.滤波算法 146 | 1).PreScanKey & NowScanKey : 电平触发 147 | 2).PreReadKey & (PreScanKey ^ NowScanKey) : 采样保持 148 | 3).NowReadKey = 1) | 2) : 带采样保持的电平触发 149 | 3.调用说明 150 | a.对下调用的KeyIOread()中,有效按键必须为高电平,且每个bit表示一个按键值 151 | b.应用调用该函数的间隔应该在20ms~50ms,在调用间隔内的毛刺均可滤除。 152 | *******************************************************************************/ 153 | void KeyScan(void) 154 | { 155 | KEY_TYPE NowScanKey = 0; //当前按键值扫描值 156 | KEY_TYPE NowReadKey = 0; //当前按键值 157 | //KEY_TYPE KeyPressDown = 0; //按键按下 158 | KEY_TYPE KeyRelease = 0; //按键释放 159 | NowScanKey = KeyIOread(); 160 | NowReadKey = (PreScanKey&NowScanKey)| //电平触发 161 | PreReadKey&(PreScanKey^NowScanKey); //采样保持(即消抖) 162 | 163 | //KeyPressDown = NowReadKey & (NowReadKey ^ PreReadKey); //上升沿触发 164 | KeyRelease = PreReadKey & (NowReadKey ^ PreReadKey); //下降沿触发 165 | 166 | #if LONG_KEY_EN > 0 167 | if(NowReadKey == PreReadKey && NowReadKey) //用电平触发做长按键的有效判据 168 | { 169 | KeyPressTmr++; 170 | if(KeyPressTmr >= KEY_PRESS_TMR) //长按判断周期到,保存相应长按键值 171 | { 172 | if(NowReadKey & ~(KEY_LONG_SHIFT)) //长按键模式一 173 | { 174 | KeyBufIn(NowReadKey | KeyShift); //长按键重复输出 175 | } 176 | else if(NowReadKey & (KEY_LONG_SHIFT) & ~KeyMask ) //长按键模式二 177 | { 178 | KeyBufIn(~(NowReadKey | KeyShift)); //长按键反码输出作为第二功能键 179 | } 180 | KeyPressTmr = 0; //重置连按周期,准备获取下1个长按键 181 | KeyMask = NowReadKey; 182 | } 183 | } 184 | else{ 185 | KeyPressTmr = KEY_PRESS_DLY; //按键变化,重置按键判断周期 186 | } 187 | #endif 188 | 189 | if(KeyRelease) 190 | { //短按键判断 191 | if(KeyRelease &(~KeyMask)&& !NowReadKey) 192 | { 193 | KeyShift ^= (KeyRelease & (KEY_SHORT_SHIFT)); //shift按键码(边缘触发) 194 | KeyBufIn(KeyRelease | KeyShift | PreReadKey); 195 | } 196 | else 197 | { 198 | KeyMask = 0; 199 | } 200 | } 201 | 202 | PreScanKey = NowScanKey; 203 | PreReadKey = NowReadKey; 204 | } 205 | 206 | /** **************************************************************************** 207 | @brief 按键初始化 208 | *******************************************************************************/ 209 | __weak void KeyInit( void ) 210 | { 211 | //按键初始化,输入,浮空,低速 212 | GpioInit2Input(K_UP ,GPIO_NOPULL,GPIO_SPEED_FREQ_LOW); 213 | GpioInit2Input(K_DN ,GPIO_NOPULL,GPIO_SPEED_FREQ_LOW); 214 | GpioInit2Input(K_LT ,GPIO_NOPULL,GPIO_SPEED_FREQ_LOW); 215 | GpioInit2Input(K_RT ,GPIO_NOPULL,GPIO_SPEED_FREQ_LOW); 216 | GpioInit2Input(K_ENT ,GPIO_NOPULL,GPIO_SPEED_FREQ_LOW); 217 | GpioInit2Input(K_ESC ,GPIO_NOPULL,GPIO_SPEED_FREQ_LOW); 218 | GpioInit2Input(K_INC ,GPIO_NOPULL,GPIO_SPEED_FREQ_LOW); 219 | GpioInit2Input(K_DEC ,GPIO_NOPULL,GPIO_SPEED_FREQ_LOW); 220 | GpioInit2Input(K_FUN ,GPIO_NOPULL,GPIO_SPEED_FREQ_LOW); 221 | } 222 | 223 | /** **************************************************************************** 224 | @brief 从buf中获得一个按键值 225 | @return 回按键值,无按键返回0xFF 226 | *******************************************************************************/ 227 | uint32_t KeyGet(void) 228 | { 229 | return (uint32_t)KeyBufOut(); 230 | } 231 | 232 | /** **************************************************************************** 233 | @brief 判断是否有按键按下 234 | @return buf中按键的数量 235 | *******************************************************************************/ 236 | uint8_t KeyGetBufLen (void) 237 | { 238 | return KeyBufInIdx - KeyBufOutIdx; 239 | } 240 | 241 | /** **************************************************************************** 242 | @brief 清空buff中所有按键值 243 | *******************************************************************************/ 244 | void KeyFlush(void) 245 | { 246 | KeyBufOutIdx = KeyBufInIdx; 247 | } 248 | -------------------------------------------------------------------------------- /key.h: -------------------------------------------------------------------------------- 1 | /** **************************************************************************** 2 | * @file key.h 3 | * @author mojinpan 4 | * @copyright (c) 2018 - 2020 mojinpan 5 | * @brief 按键驱动 6 | * 7 | * @par 功能说明 8 | * @details 9 | * 1.支持最大64个按键(数量可配置) 10 | * 2.支持按键消抖处理(可滤掉小于2个扫描周期的毛刺) 11 | * 3.支持按键环形缓冲区(长度可配置) 12 | * 4.支持4种不同按键模式:A:短按键 B:shift键 C:长按单发 D:长按连发 13 | * 5.短按键 :短按直接输出键值 14 | * 6.shift键 :点击后除了输出一次短按键外,还将后续所有其他按键的键值改为,shift键+按键值(包括长短按键) 15 | * 7.长按连发 :长按一定时间后连续输出按键键值 16 | * 8.长按单发 :长按一定时间后反码输出键值(仅一次) 17 | * 9.4种不同按键模式可相互叠加使用,所有按键功能都能并发输出 18 | * 19 | * @par 移植说明 20 | * @details 21 | * 1.根据具体情况编写KeyIOread()和KeyInit(). 22 | * 2.每20ms~50ms调用KeyScan()扫描按键,调用KeyGetBufLen()判断是否有按键,调用KeyGet()获得按键值. 23 | *******************************************************************************/ 24 | #ifndef __KEY__ 25 | #define __KEY__ 26 | 27 | /******************************************************************************* 28 | Header Files 头文件 29 | *******************************************************************************/ 30 | #include "bsp.h" 31 | #include "stdbool.h" 32 | #include "stdint.h" 33 | /******************************************************************************* 34 | Key Scancode 按键扫描码 35 | *******************************************************************************/ 36 | ///* @brief 按键键值,每个按键占1bit,不得重复 37 | typedef enum 38 | { 39 | KEY_UP = 0x0001, 40 | KEY_DN = 0x0002, 41 | KEY_LT = 0x0004, 42 | KEY_RT = 0x0008, 43 | KEY_ENT = 0x0010, 44 | KEY_ESC = 0x0020, 45 | KEY_INC = 0x0040, 46 | KEY_DEC = 0x0080, 47 | KEY_FUN = 0x0100 48 | 49 | KEY_UP_L = 0xFFFE, 50 | KEY_DN_L = 0xFFFD, 51 | 52 | KEY_UP_SF = 0x0101, 53 | KEY_DN_SF = 0x0102, 54 | KEY_LT_SF = 0x0104, 55 | KEY_RT_SF = 0x0108, 56 | KEY_ENT_SF = 0x0110, 57 | KEY_ESC_SF = 0x0120, 58 | KEY_INC_SF = 0x0140, 59 | KEY_DEC_SF = 0x0180 60 | } KEY_value; 61 | /******************************************************************************* 62 | Drive Config 驱动配置 63 | *******************************************************************************/ 64 | #define KEY_MAX_NUM 11 //定义最大按键数量(1~64) 65 | #define KEY_BUF_SIZE 8 //定义按键缓冲区大小(2,4,8,16,32,64,128,256) 66 | #define KEY_LONG_EN 1 //定义是否支持长按键(1 or 0) 67 | #define KEY_SHORT_SHIFT KEY_FUN //定义shift键,短按有效(0 or 按键扫描码) 68 | 69 | #if KEY_LONG_EN > 0 70 | #define KEY_PRESS_DLY 40 //定义长按键延时n个扫描周期开始判定有效值(1~256) 71 | #define KEY_PRESS_TMR 5 //定义长按键n个扫描周期为1次有效扫描值(1~256) 72 | #define KEY_LONG_SHIFT KEY_UP|KEY_DN //长按键反码输出(仅一次),未定义的长按连续输出(0 or 按键扫描码) 73 | #endif 74 | /******************************************************************************* 75 | Function declaration 函数声明 76 | *******************************************************************************/ 77 | void KeyInit(void); //按键初始化函数 78 | void KeyScan(void); //按键扫描函数,20ms~50ms定时调用 79 | uint8_t KeyGetBufLen(void); //按键判断函数,判断是否有按键按下 80 | uint32_t KeyGet(void); //按键获得函数,获取具体按键值,无按键时返回0 81 | void KeyFlush(void); //清空按键buf 82 | #endif 83 | 84 | 85 | 86 | --------------------------------------------------------------------------------