本模組模仿MultiButton實現的。GitHub:https://github.com/0x1abin/MultiButton
按鍵狀態參考DALI協定301部分按鍵狀態。
分享測試檔案:
連結:https://pan.baidu.com/s/1dqXc-_ycR-Tl-KQtsxJs4A
提取碼:1234
按鍵狀態分為以下狀態:
1 #include "bsp_includes.h" 2 #include <string.h> 3 4 static KeyInfo_Def *pHead_Node = NULL; 5 /************************************************************************** 6 * @brief 初始化連結串列頭結點 7 **************************************************************************/ 8 void List_Init(void) 9 { 10 pHead_Node = NULL; 11 } 12 /************************************************************************** 13 * @brief 獲取按鍵當前觸發的事件 14 **************************************************************************/ 15 u8 Get_KeyCurEvent(KeyInfo_Def *pHandle) 16 { 17 return (u8)(pHandle->byEvent); 18 } 19 /************************************************************************** 20 * @brief 把新增的按鍵加入連結串列 21 **************************************************************************/ 22 int Add_KeyToList(KeyInfo_Def *pCurNode) 23 { 24 KeyInfo_Def *pTargetNode = pHead_Node; 25 while (pTargetNode) 26 { 27 if (pTargetNode == pCurNode) 28 { 29 return -1; // already exist. 30 } 31 pTargetNode = pTargetNode->pNext; // find Null node 32 } 33 34 pCurNode->pNext = pHead_Node; 35 pHead_Node = pCurNode; 36 return 0; // add success 37 } 38 39 /************************************************************************** 40 * @brief 註冊按鍵資訊 41 **************************************************************************/ 42 void Key_Attach(KeyInfo_Def *pHandle, GetIOStatus pFunc1, KeyEventProcess pFunc2, uint8_t byState) 43 { 44 memset(pHandle, 0, sizeof(KeyInfo_Def)); 45 pHandle->dwPressedTicks = 0; 46 pHandle->dwReleasedTicks = 0; 47 pHandle->dwLongPressRepeat_Ticks = 0; 48 pHandle->byEvent = KeyEvent_Idle; 49 pHandle->byKeyStatus = Key_IDLE; 50 pHandle->byDebounce_Count = 0; 51 pHandle->byMultiplePressEnable = byState; 52 pHandle->pGetIOLevel_Func = pFunc1; 53 pHandle->pProcess_Func = pFunc2; 54 pHandle->byKey_Level = pHandle->pGetIOLevel_Func(); 55 56 Add_KeyToList(pHandle); 57 } 58 59 void KeyEvent_Process(KeyInfo_Def *handle, KeyEvent_Def keyEvent) 60 { 61 handle->byEvent = keyEvent; 62 handle->pProcess_Func(handle, handle->byEvent); 63 } 64 /************************************************************************** 65 * @brief 按鍵狀態機 66 **************************************************************************/ 67 void Key_handler(KeyInfo_Def *pHandle) 68 { 69 uint8_t byRead_IO_Level = pHandle->pGetIOLevel_Func(); 70 71 /*------------button debounce handle---------------*/ 72 if (byRead_IO_Level != pHandle->byKey_Level) // not equal to prev one 73 { 74 // continue read 3 times same new level change 75 if (++(pHandle->byDebounce_Count) >= DEBOUNCE_TICKS) 76 { 77 pHandle->byKey_Level = byRead_IO_Level; 78 pHandle->byDebounce_Count = 0; 79 if (pHandle->byKey_Level == Pressed) 80 { 81 KeyEvent_Process(pHandle, KeyEvent_PutDown); 82 } 83 else 84 { 85 KeyEvent_Process(pHandle, KeyEvent_RealeaseUp); 86 } 87 } 88 } 89 else 90 { // leved not change ,counter reset. 91 pHandle->byDebounce_Count = 0; 92 } 93 94 if (pHandle->dwReleasedTicks < 300000) // 300s 95 pHandle->dwReleasedTicks++; 96 if (pHandle->dwPressedTicks < 300000) 97 pHandle->dwPressedTicks++; 98 99 if (byRead_IO_Level != pHandle->byKey_Level) 100 { 101 if (byRead_IO_Level == Pressed) 102 pHandle->dwPressedTicks = 0; 103 else 104 pHandle->dwReleasedTicks = 0; 105 } 106 107 switch (pHandle->byKeyStatus) 108 { 109 case Key_IDLE: 110 if (pHandle->byKey_Level == Pressed) 111 { 112 if (pHandle->dwPressedTicks >= ShortPress_Ticks) 113 { 114 KeyEvent_Process(pHandle, KeyEvent_LongPressStart); 115 pHandle->dwLongPressRepeat_Ticks = 0; 116 pHandle->byKeyStatus = Key_LongPress; 117 } 118 else 119 { 120 pHandle->byKeyStatus = Key_ACK; 121 } 122 } 123 else 124 { 125 pHandle->byKeyStatus = Key_IDLE; 126 } 127 break; 128 case Key_ACK: 129 if (pHandle->byKey_Level == Pressed) 130 { 131 if (pHandle->dwPressedTicks >= ShortPress_Ticks) 132 { 133 KeyEvent_Process(pHandle, KeyEvent_LongPressStart); 134 pHandle->dwLongPressRepeat_Ticks = 0; 135 pHandle->byKeyStatus = Key_LongPress; 136 } 137 } 138 else 139 { 140 if (pHandle->byMultiplePressEnable == DPress_Disable) 141 { 142 KeyEvent_Process(pHandle, KeyEvent_Click); 143 pHandle->byKeyStatus = Key_IDLE; 144 } 145 else 146 { 147 pHandle->byKeyStatus = Key_WaitDoublePress; 148 } 149 } 150 break; 151 case Key_WaitDoublePress: 152 if (pHandle->byKey_Level == Pressed) 153 { 154 if (pHandle->dwReleasedTicks <= DoubleClickIdle_Ticks) 155 { 156 if (pHandle->byMultiplePressEnable == DPress_Enable) 157 KeyEvent_Process(pHandle, KeyEvent_DoubleClick); 158 else 159 KeyEvent_Process(pHandle, KeyEvent_PutDown); 160 pHandle->byKeyStatus = Key_WaitDoublePressIdle; 161 } 162 } 163 else 164 { 165 if (pHandle->dwReleasedTicks > DoubleClickIdle_Ticks) 166 { 167 KeyEvent_Process(pHandle, KeyEvent_Click); 168 pHandle->byKeyStatus = Key_IDLE; 169 } 170 } 171 break; 172 case Key_WaitDoublePressIdle: 173 if (pHandle->byKey_Level == Released) 174 { 175 pHandle->byKeyStatus = Key_IDLE; 176 } 177 break; 178 case Key_LongPress: 179 if (pHandle->byKey_Level == Pressed) 180 { 181 if (pHandle->dwPressedTicks > Stuck_Ticks) 182 { 183 KeyEvent_Process(pHandle, KeyEvent_Stuck); 184 pHandle->byKeyStatus = Key_STUCK; 185 } 186 else if (pHandle->dwLongPressRepeat_Ticks > LongPressRepeat_Ticks) 187 { 188 KeyEvent_Process(pHandle, KeyEvent_LongPressRepeat); 189 pHandle->dwLongPressRepeat_Ticks = 0; 190 } 191 else 192 { 193 pHandle->dwLongPressRepeat_Ticks++; 194 } 195 } 196 else 197 { 198 KeyEvent_Process(pHandle, KeyEvent_LongPressEnd); 199 pHandle->byKeyStatus = Key_IDLE; 200 } 201 break; 202 203 case Key_STUCK: 204 if (pHandle->byKey_Level == Released) 205 { 206 KeyEvent_Process(pHandle, KeyEvent_Free); 207 pHandle->byKeyStatus = Key_IDLE; 208 } 209 default: 210 break; 211 } 212 } 213 /************************************************************************** 214 * @brief 移除按鍵節點 215 **************************************************************************/ 216 void Remove_Key(KeyInfo_Def *pTarget) 217 { 218 KeyInfo_Def **ppCur; 219 KeyInfo_Def *entry = *ppCur; 220 for (ppCur = &pHead_Node; (*ppCur) != NULL;) 221 { 222 if (entry == pTarget) 223 { 224 *ppCur = entry->pNext; 225 // free(entry); 226 } 227 else 228 { 229 ppCur = &entry->pNext; 230 } 231 } 232 } 233 /************************************************************************** 234 * @brief 毫秒處理常式 235 **************************************************************************/ 236 void Key_Ticks_1ms(void) 237 { 238 KeyInfo_Def *pTarget; 239 for (pTarget = pHead_Node; pTarget; pTarget = pTarget->pNext) 240 { 241 if (pTarget == NULL) 242 return; 243 Key_handler(pTarget); 244 } 245 }
1 #ifndef __BSP_KEY_H__ 2 #define __BSP_KEY_H__ 3 4 #include "bsp_includes.h" 5 6 #define DEBOUNCE_TICKS 10 7 8 #define ShortPress_Ticks 500 9 #define DoubleClickIdle_Ticks 300 10 #define Stuck_Ticks 20000 11 #define LongPressRepeat_Ticks 200 12 13 #define DPress_Enable 1 14 #define DPress_Disable 0 15 16 typedef uint8_t (*GetIOStatus)(void); 17 typedef void (*KeyEventProcess)(void *, uint8_t); 18 19 typedef enum 20 { 21 Released = 1, 22 Pressed = 0 23 } IOStatus_Def; 24 25 typedef enum 26 { 27 Key_IDLE = 0, 28 Key_ACK, 29 Key_WaitDoublePress, 30 Key_WaitDoublePressIdle, 31 Key_LongPress, 32 Key_STUCK 33 } KeyStatus_Def; 34 35 typedef enum 36 { 37 KeyEvent_Idle = 0, 38 KeyEvent_PutDown, 39 KeyEvent_RealeaseUp, 40 KeyEvent_Click, 41 KeyEvent_DoubleClick, 42 KeyEvent_LongPressStart, 43 KeyEvent_LongPressRepeat, 44 KeyEvent_LongPressEnd, 45 KeyEvent_Stuck, 46 KeyEvent_Free 47 } KeyEvent_Def; 48 49 typedef struct Key 50 { 51 struct Key *pNext; 52 uint32_t dwPressedTicks; 53 uint32_t dwReleasedTicks; 54 uint32_t dwLongPressRepeat_Ticks; 55 uint8_t byDebounce_Count; 56 uint8_t byEvent; 57 uint8_t byKey_Level; 58 uint8_t byKeyStatus; 59 uint8_t byMultiplePressEnable; 60 GetIOStatus pGetIOLevel_Func; 61 KeyEventProcess pProcess_Func; 62 } KeyInfo_Def;
如需要移植需注意: