為什么要設計FIFO,安富萊大佬的回答:
1. 可靠地記錄每一個按鍵事件,避免遺漏按鍵事件。特別是需要實作按鍵的按下、長按、自動連發、彈起等事件時。
2. 讀取按鍵的函式可以設計為非阻塞的,不需要等待按鍵抖動濾波處理完畢。
3. 按鍵FIFO程式在嘀嗒定時器中定期的執行檢測,不需要在主程式中一直做檢測,這樣可以有效地降低系統資源消耗。
typedef struct
{
下面是一個函式指標,指向判斷按鍵手否按下的函式
uint8_t (*IsKeyDownFunc)(void); 按鍵按下的判斷函式,1表示按下
uint8_t Count; 濾波器計數器
uint16_t LongCount; 長按計數器
uint16_t LongTime; 按鍵按下持續時間, 0表示不檢測長按
uint8_t State; 按鍵當前狀態(按下還是彈起)
uint8_t RepeatSpeed; 連續按鍵周期
uint8_t RepeatCount; 連續按鍵計數器
}KEY_T;
bsp_DetectKey這個函式key.c檢測的核心

typedef struct
{
下面是一個函式指標,指向判斷按鍵手否按下的函式
uint8_t (*IsKeyDownFunc)(void); 按鍵按下的判斷函式,1表示按下
uint8_t Count; 濾波器計數器
uint16_t LongCount; 長按計數器
uint16_t LongTime; 按鍵按下持續時間, 0表示不檢測長按
uint8_t State; 按鍵當前狀態(按下還是彈起)
uint8_t RepeatSpeed; 連續按鍵周期
uint8_t RepeatCount; 連續按鍵計數器
}KEY_T;
主要就是對這個結構體的進行解算,bsp_KeyScan()函式里面不斷進行掃描,bsp_KeyScan()主要是放在bsp_RunPer10ms(),然后丟到SysTick_Handler中10ms的掃描一次.
在bsp_DetectKey()函式里面直接呼叫外部結果提s_tBtn,然后進行數值的改變。
有兩個初始化,一個是對結構體的值進行默認初始化,還有一個就是硬體的初始化,和我們普通的硬體埠初始化是一樣的。
/* 對按鍵FIFO讀寫指標清零 */
s_tKey.Read = 0;
s_tKey.Write = 0;
s_tKey.Read2 = 0;
軟體初始化需要拿出來單獨說一下,初始化里面首先將FIFO緩沖設定初始值.
檔案定義了一個結構體陣列static KEY_T s_tBtn[KEY_COUNT],KEY_COUNT是按鍵的數量,而且這個數值是放在本檔案中使用的,外部是無法呼叫的,真正讀取鍵值的方式就是s_tBtn[0].IsKeyDownFunc = IsKeyDown1;
KEY_COUNT是按鍵的序號
typedef struct
{
uint8_t Buf[KEY_FIFO_SIZE]; /* 鍵值緩沖區 */
uint8_t Read; /* 緩沖區讀指標1 */
uint8_t Write; /* 緩沖區寫指標 */
uint8_t Read2; /* 緩沖區讀指標2 */
}KEY_FIFO_T;
static KEY_FIFO_T s_tKey; /* 按鍵FIFO變數,結構體 */
//bsp_PutKey(); 將一個鍵值壓入按鍵FIFO.用來模擬一個按鍵
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;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/109176.html
標籤:單片機/工控
