日韩一区二区三区精品,欧美疯狂xxxxbbbb牲交,热99re久久免费视精品频,人妻互换 综合,欧美激情肉欲高潮视频

歷史上的今天

今天是:2025年05月29日(星期四)

正在發(fā)生

2018年05月29日 | STM32F4 按鍵FIFO設(shè)計

發(fā)布者:會飛的笨魚 來源: eefocus關(guān)鍵字:STM32F4  按鍵FIFO 手機看文章 掃描二維碼
隨時隨地手機看文章

設(shè)計按鍵 FIFO 主要有三個方面的好處: 
1.可以有效的記錄按鍵事件的發(fā)生,特別是需要實現(xiàn)按鍵的按下,長按,彈起等事件,使用 FIFO的方式來實現(xiàn)是一種非常好的思路。 
2.系統(tǒng)是非阻塞的,這樣系統(tǒng)在檢測到按鍵按下的情況下,由于機械按鍵抖動的原因不需要在這里等待一段時間,然后再確定按鍵是否按下。 
3.按鍵 FIFO 程序在嘀嗒定時器中定期的執(zhí)行檢測,不需要在主程序中一直做檢測,這樣可以有效的降低系統(tǒng)資源消耗。 

關(guān)于按鍵是否該使用中斷方式去實現(xiàn)的問題,很多初學者都比較模糊,我這里從兩方面簡單說一下,純屬個人見解,如果那位有更好的意見,歡迎提出來。 

從裸機的角度分析 
中斷方式:中斷方式可以有效的檢測到按鍵按下的消息,并執(zhí)行相應的程序,但是用中斷方式實現(xiàn)按鍵 FIFO 相對就有點麻煩,如果每個按鍵都是獨立的接一個 IO 引腳,需要我們給每個 IO都設(shè)置一個中斷,程序中過多的中斷會影響系統(tǒng)的穩(wěn)定性。 
查詢方式:查詢方式有一個最大的缺點就是需要程序定期的去執(zhí)行查詢,耗費一定的系統(tǒng)資源,實際上耗費不了多大的系統(tǒng)資源,因為這種查詢方式也只是查詢按鍵是否按下,按鍵事件的執(zhí)行還是在主程序里面實現(xiàn)。 
從 OS 的角度分析 
中斷方式:在 OS 中要盡可能少用中斷方式,因為在 RTOS 中過多的使用中斷會影響系統(tǒng)的穩(wěn)定性和可預見性(搶占式調(diào)度的 OS 基本沒有可預見性,基于時間觸發(fā)調(diào)度的可預見性要好很多)。比較重要的事件處理需要用中斷的方式。 

查詢方式:對于用戶按鍵推薦使用這種查詢方式來實現(xiàn),現(xiàn)在的 OS 基本都帶有 CPU 利用率的功能,這個按鍵 FIFO 占用的還是很小的,基本都在%1 以下。

這個按鍵 FIFO 程序主要用于掃描掃描獨立按鍵,具有軟件濾波機制,具有按鍵 FIFO??梢詸z測如下事件: 
1.   按鍵按下 
2.   按鍵彈起 
3.   長按鍵 
4.   長按時自動連發(fā) 

聲明代碼如下:


  1. /** 

  2.   ****************************************************************************** 

  3.   * @file       : bsp_key.h  

  4.   * @author     : xiaofeng  

  5.   * @version    : V1.0 

  6.   * @date       : 2015.05.21 

  7.   * @brief      : STM32F4 KEY FIFO 

  8.   ****************************************************************************** 

  9.   * @attention: 

  10.   * 

  11.   ****************************************************************************** 

  12.   */  

  13.       

  14. /* Define to prevent recursive inclusion -------------------------------------*/  

  15. #ifndef __BSP_KEY_H__  

  16. #define __BSP_KEY_H__  

  17.   

  18. #ifdef __cplusplus  

  19.  extern "C" {  

  20. #endif  

  21.   

  22. /* Includes ------------------------------------------------------------------*/  

  23. #include "stm32f4xx.h"  

  24.   

  25. /* Exported types ------------------------------------------------------------*/  

  26.   

  27. // 按鍵ID  

  28. typedef enum  

  29. {  

  30.     KID_K1 = 0,  

  31.     KID_K2,  

  32.     KID_K3,  

  33.     KID_K4  

  34. }KEY_ID_E;  

  35.   

  36. /* 

  37.     定義鍵值代碼, 必須按如下次序定時每個鍵的按下、彈起和長按事件 

  38.     推薦使用enum, 不用#define,原因: 

  39.     (1) 便于新增鍵值,方便調(diào)整順序,使代碼看起來舒服點 

  40.     (2) 編譯器可幫我們避免鍵值重復。 

  41. */  

  42. typedef enum  

  43. {  

  44.     KEY_NONE = 0,           /* 0 表示按鍵事件 */  

  45.   

  46.     KEY1_DOWN,              /* 1鍵按下 */  

  47.     KEY1_UP,                /* 1鍵彈起 */  

  48.     KEY1_LONG,              /* 1鍵長按 */  

  49.   

  50.     KEY2_DOWN,              /* 2鍵按下 */  

  51.     KEY2_UP,                /* 2鍵彈起 */  

  52.     KEY2_LONG,              /* 2鍵長按 */  

  53. }KEY_ENUM;  

  54.   

  55. /* Exported constants --------------------------------------------------------*/  

  56. /* Exported macro ------------------------------------------------------------*/  

  57. #define KEY_COUNT           2       // 按鍵個數(shù)  

  58. #define KEY_FIFO_SIZE       10      // 按鍵FIFO大小  

  59. #define KEY_FILTER_TIME     5       // 按鍵濾波時間50ms, 只有連續(xù)檢測到50ms狀態(tài)不變才認為有效,包括彈起和按下兩種事件  

  60. #define KEY_LONG_TIME       0       // 長按時間. 0,表示不檢測長按鍵; 其他,檢測長按鍵的時間  

  61. #define KEY_REPEAT_SPEED    0       // 長按鍵連發(fā)速度. 0,表示不支持連發(fā),上報長按事件;其他,連發(fā)按下  

  62.   

  63. // 按鍵口對應的RCC時鐘及引腳  

  64. #define RCC_ALL_KEY     (RCC_AHB1Periph_GPIOA )  

  65.   

  66. #define GPIO_PORT_K1    GPIOA  

  67. #define GPIO_PIN_K1     GPIO_Pin_0  

  68.   

  69. #define GPIO_PORT_K2    GPIOD  

  70. #define GPIO_PIN_K2     GPIO_Pin_1  

  71.   

  72. /* Exported functions --------------------------------------------------------*/   

  73. void KEY_Init(void);  

  74. void KEY_Scan(void);  

  75.   

  76. void KEY_FIFO_Clear(void);  

  77. uint8_t KEY_FIFO_Get(void);  

  78.   

  79. uint8_t KEY_GetState(KEY_ID_E ucKeyID);  

  80. void KEY_SetParam(uint8_t ucKeyID, uint16_t LongTime, uint8_t  RepeatSpeed);  

  81.   

  82. #ifdef __cplusplus  

  83. }  

  84. #endif  

  85.   

  86. #endif   

  87.   

  88.   

  89. /*****END OF FILE****/  


實現(xiàn)代碼如下:


  1. /** 

  2.   ****************************************************************************** 

  3.   * @file       : bsp_key.h  

  4.   * @author     : xiaofeng  

  5.   * @version    : V1.0 

  6.   * @date       : 2015.05.21 

  7.   * @brief      : STM32F4 KEY FIFO 

  8.   ****************************************************************************** 

  9.   * @attention: 

  10.   * 

  11.   ****************************************************************************** 

  12.   */  

  13. /* Includes ------------------------------------------------------------------*/  

  14. #include "bsp_key.h"  

  15. /* Private typedef -----------------------------------------------------------*/  

  16. // 每個按鍵對應1個全局的結(jié)構(gòu)體變量。  

  17. typedef struct  

  18. {  

  19.     /* 下面是一個函數(shù)指針,指向判斷按鍵手否按下的函數(shù) */  

  20.     uint8_t (*IsKeyDownFunc)(void); /* 按鍵按下的判斷函數(shù),1表示按下 */  

  21.   

  22.     uint8_t  Count;         /* 濾波器計數(shù)器 */  

  23.     uint8_t  State;         /* 按鍵當前狀態(tài)(按下還是彈起) */  

  24.     uint16_t LongCount;     /* 長按計數(shù)器 */  

  25.     uint16_t LongTime;      /* 按鍵按下持續(xù)時間, 0表示不檢測長按 */  

  26.     uint8_t  RepeatSpeed;   /* 連續(xù)按鍵周期 */  

  27.     uint8_t  RepeatCount;   /* 連續(xù)按鍵計數(shù)器 */  

  28. }KEY_T;  

  29.   

  30. // 按鍵FIFO用到變量   

  31. typedef struct  

  32. {  

  33.     uint8_t Buf[KEY_FIFO_SIZE];     /* 鍵值緩沖區(qū) */  

  34.     uint8_t Read;                   /* 緩沖區(qū)讀指針 */  

  35.     uint8_t Write;                  /* 緩沖區(qū)寫指針 */  

  36. }KEY_FIFO_T;  

  37.   

  38. /* Private define ------------------------------------------------------------*/  

  39. /* Private macro -------------------------------------------------------------*/  

  40. /* Private variables ---------------------------------------------------------*/  

  41. static KEY_T s_tBtn[KEY_COUNT];  

  42. static KEY_FIFO_T s_tKey;       /* 按鍵FIFO變量,結(jié)構(gòu)體 */  

  43.   

  44. /* Private function prototypes -----------------------------------------------*/  

  45. static void KEY_FIFO_Init(void);  

  46. static void KEY_GPIO_Config(void);  

  47. static void KEY_FIFO_Put(uint8_t _KeyCode);  

  48. static void KEY_Detect(uint8_t i);  

  49.   

  50. /* Private functions ---------------------------------------------------------*/  

  51. /** 

  52.   * @brief  :   KEY初始化 

  53.   * @note       :   

  54.   * @param  : 

  55.   * @retval : 

  56.   */  

  57. void KEY_Init(void)  

  58. {  

  59.     KEY_GPIO_Config();  

  60.     KEY_FIFO_Init();  

  61. }  

  62.   

  63. /** 

  64.   * @brief  : 清空按鍵FIFO緩沖區(qū) 

  65.   * @note   : 無   

  66.   * @param  : 無 

  67.   * @retval : 無 

  68.   */  

  69. void KEY_FIFO_Clear(void)  

  70. {  

  71.     s_tKey.Read = s_tKey.Write;  

  72. }  

  73.   

  74. /** 

  75.   * @brief  : 從按鍵FIFO緩沖區(qū)讀取一個鍵值 

  76.   * @note   : 無   

  77.   * @param  : 

  78.   * @retval : 按鍵代碼 

  79.   */  

  80. uint8_t KEY_FIFO_Get(void)  

  81. {  

  82.     uint8_t ret;  

  83.   

  84.     if (s_tKey.Read == s_tKey.Write)  

  85.     {  

  86.         return KEY_NONE;  

  87.     }  

  88.     else  

  89.     {  

  90.         ret = s_tKey.Buf[s_tKey.Read];  

  91.   

  92.         if (++s_tKey.Read >= KEY_FIFO_SIZE)  

  93.         {  

  94.             s_tKey.Read = 0;  

  95.         }  

  96.         return ret;  

  97.     }  

  98. }  

  99. /** 

  100.   * @brief  : 讀取按鍵的狀態(tài) 

  101.   * @note   : 無   

  102.   * @param  : ucKeyID : 按鍵ID,從0開始 

  103.   * @retval : 1 表示按下, 0 表示未按下 

  104.   */  

  105. uint8_t KEY_GetState(KEY_ID_E ucKeyID)  

  106. {  

  107.     return s_tBtn[ucKeyID].State;  

  108. }  

  109. /** 

  110.   * @brief  : 設(shè)置按鍵參數(shù) 

  111.   * @note   : 無   

  112.   * @param  : ucKeyID : 按鍵ID,從0開始 

  113.   *           LongTime : 長按事件時間 

  114.   *           RepeatSpeed : 連發(fā)速度 

  115.   * @retval : 無 

  116.   */  

  117. void KEY_SetParam(uint8_t ucKeyID, uint16_t LongTime, uint8_t  RepeatSpeed)  

  118. {  

  119.     s_tBtn[ucKeyID].LongTime = LongTime;        /* 長按時間 0 表示不檢測長按鍵事件 */  

  120.     s_tBtn[ucKeyID].RepeatSpeed = RepeatSpeed;  /* 長按鍵連發(fā)的速度,0表示不支持連發(fā) */  

  121.     s_tBtn[ucKeyID].RepeatCount = 0;            /* 連發(fā)計數(shù)器 */  

  122. }  

  123.   

  124. /** 

  125.   * @brief  : 掃描所有按鍵。非阻塞,被周期性的調(diào)用(如systick中斷) 

  126.   * @note   : 無   

  127.   * @param  : 無 

  128.   * @retval : 無 

  129.   */  

  130. void KEY_Scan(void)  

  131. {  

  132.     uint8_t i;  

  133.   

  134.     for (i = 0; i < KEY_COUNT; i++)  

  135.     {  

  136.         KEY_Detect(i);  

  137.     }  

  138. }  

  139.   

  140. /***************************************************************************/  

  141. /** 

  142.   * @brief  : 配置按鍵對應的GPIO 

  143.   * @note   : 無   

  144.   * @param  : 無 

  145.   * @retval : 無 

  146.   */  

  147. static void KEY_GPIO_Config(void)  

  148. {  

  149.     GPIO_InitTypeDef GPIO_InitStructure;  

  150.   

  151.     /* 第1步:打開GPIO時鐘 */  

  152.     RCC_AHB1PeriphClockCmd(RCC_ALL_KEY, ENABLE);  

  153.   

  154.     /* 第2步:配置所有的按鍵GPIO為浮動輸入模式(實際上CPU復位后就是輸入狀態(tài)) */  

  155.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;        /* 設(shè)為輸入口 */  

  156.     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      /* 設(shè)為推挽模式 */  

  157.     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;    /* 無需上下拉電阻 */  

  158.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   /* IO口最大速度 */  

  159.   

  160.     GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K1;  

  161.     GPIO_Init(GPIO_PORT_K1, &GPIO_InitStructure);  

  162.   

  163.     GPIO_InitStructure.GPIO_Pin = GPIO_PIN_K2;  

  164.     GPIO_Init(GPIO_PORT_K2, &GPIO_InitStructure);  

  165. }  

  166. /** 

  167.   * @brief  : 判斷按鍵是否按下 

  168.   * @note   : 無   

  169.   * @param  : 無 

  170.   * @retval : 1 表示按下,0表示未按下 

  171.   */  

  172. static uint8_t IsKey1Down(void) {if (GPIO_ReadInputDataBit(GPIO_PORT_K1, GPIO_PIN_K1) == 0) return 1;else return 0;}  

  173. static uint8_t IsKey2Down(void) {if (GPIO_ReadInputDataBit(GPIO_PORT_K2, GPIO_PIN_K2) == 0) return 1;else return 0;}  

  174. /** 

  175.   * @brief  : 初始化按鍵變量 

  176.   * @note   : 無   

  177.   * @param  : 無 

  178.   * @retval : 無 

  179.   */  

  180. static void KEY_FIFO_Init(void)  

  181. {  

  182.     uint8_t i;  

  183.   

  184.     /* 對按鍵FIFO讀寫指針清零 */  

  185.     s_tKey.Read = 0;  

  186.     s_tKey.Write = 0;  

  187.   

  188.     /* 給每個按鍵結(jié)構(gòu)體成員變量賦一組缺省值 */  

  189.     for (i = 0; i < KEY_COUNT; i++)  

  190.     {  

  191.         s_tBtn[i].LongTime = KEY_LONG_TIME;         /* 長按時間 0 表示不檢測長按鍵事件 */  

  192.         s_tBtn[i].Count = KEY_FILTER_TIME / 2;      /* 計數(shù)器設(shè)置為濾波時間的一半 */  

  193.         s_tBtn[i].State = 0;                        /* 按鍵缺省狀態(tài),0為未按下 */  

  194.         s_tBtn[i].RepeatSpeed = KEY_REPEAT_SPEED;   /* 按鍵連發(fā)的速度,0表示不支持連發(fā) */  

  195.         s_tBtn[i].RepeatCount = 0;                  /* 連發(fā)計數(shù)器 */  

  196.     }  

  197.   

  198.     /* 判斷按鍵按下的函數(shù) */  

  199.     s_tBtn[0].IsKeyDownFunc = IsKey1Down;  

  200.     s_tBtn[1].IsKeyDownFunc = IsKey2Down;  

  201. }  

  202. /** 

  203.   * @brief  : 將1個鍵值壓入按鍵FIFO緩沖區(qū) 

  204.   * @note   : 無   

  205.   * @param  : KeyCode : 按鍵代碼 

  206.   * @retval : 無 

  207.   */  

  208. static void KEY_FIFO_Put(uint8_t _KeyCode)  

  209. {  

  210.     s_tKey.Buf[s_tKey.Write] = _KeyCode;  

  211.   

  212.     if (++s_tKey.Write  >= KEY_FIFO_SIZE)  

  213.     {  

  214.         s_tKey.Write = 0;  

  215.     }  

  216. }  

  217. /** 

  218.   * @brief  : 檢測一個按鍵。非阻塞狀態(tài),必須被周期性的調(diào)用 

  219.   * @note   : 無   

  220.   * @param  : 按鍵數(shù) 

  221.   * @retval : 無 

  222.   */  

  223. static void KEY_Detect(uint8_t i)  

  224. {  

  225.     KEY_T *pBtn;  

  226.   

  227.     pBtn = &s_tBtn[i];  

  228.     if (pBtn->IsKeyDownFunc())  

  229.     {// 按鍵按下  

  230.         if (pBtn->Count < KEY_FILTER_TIME)  

  231.         {  

  232.             pBtn->Count = KEY_FILTER_TIME;  

  233.         }  

  234.         else if(pBtn->Count < 2 * KEY_FILTER_TIME)  

  235.         {  

  236.             pBtn->Count++;  

  237.         }  

  238.         else  

  239.         {  

  240.             if (pBtn->State == 0)  

  241.             {  

  242.                 pBtn->State = 1;  

  243.   

  244.                 /* 發(fā)送按鈕按下的消息 */  

  245.                 KEY_FIFO_Put((uint8_t)(3 * i + 1));  

  246.             }  

  247.   

  248.             if (pBtn->LongTime > 0)  

  249.             {  

  250.                 if (pBtn->LongCount < pBtn->LongTime)  

  251.                 {  

  252.                     /* 發(fā)送按鈕持續(xù)按下的消息 */  

  253.                     if (++pBtn->LongCount == pBtn->LongTime)  

  254.                     {  

  255.                         if (pBtn->RepeatSpeed > 0)  

  256.                         {  

  257.                             pBtn->LongCount = 0;  

  258.                               

  259.                             if (++pBtn->RepeatCount >= pBtn->RepeatSpeed)  

  260.                             {  

  261.                                 pBtn->RepeatCount = 0;  

  262.                                 /* 常按鍵后,每隔10ms發(fā)送1個按鍵 */  

  263.                                 KEY_FIFO_Put((uint8_t)(3 * i + 1));  

  264.                             }            

  265.                         }  

  266.                         else  

  267.                         {  

  268.                             /* 鍵值放入按鍵FIFO */  

  269.                             KEY_FIFO_Put((uint8_t)(3 * i + 3));  

  270.                         }  

  271.                     }  

  272.                 }  

  273.             }  

  274.         }  

  275.     }  

  276.     else  

  277.     {// 按鍵抬起  

  278.         if(pBtn->Count > KEY_FILTER_TIME)  

  279.         {  

  280.             pBtn->Count = KEY_FILTER_TIME;  

  281.         }  

  282.         else if(pBtn->Count != 0)  

  283.         {  

  284.             pBtn->Count--;  

  285.         }  

  286.         else  

  287.         {  

  288.             if (pBtn->State == 1)  

  289.             {  

  290.                 pBtn->State = 0;  

  291.   

  292.                 /* 發(fā)送按鈕彈起的消息 */  

  293.                 KEY_FIFO_Put((uint8_t)(3 * i + 2));  

  294.             }  

  295.         }  

  296.   

  297.         pBtn->LongCount = 0;  

  298.         pBtn->RepeatCount = 0;  

  299.     }  

  300. }  

  301.   

  302. /*****END OF FILE****/  


關(guān)鍵字:STM32F4  按鍵FIFO 引用地址:STM32F4 按鍵FIFO設(shè)計

上一篇:STM32內(nèi)存使用及分配
下一篇:KeilMDK配置項中Use MicroLIB是干什么的

推薦閱讀

“盡管已經(jīng)逐漸接受了孩子患病的事實,但回想起診療單上出現(xiàn)‘自閉癥’這三個字時的情形,我感覺整個世界都崩塌了。”?已過去一年多的時間,軒軒媽媽有時依然會有錯覺,以為這只是一場噩夢。今年四歲的軒軒在一年前參加幼兒園面試時,老師發(fā)現(xiàn)他無法直視大人的眼睛,建議送去專業(yè)機構(gòu)進行診斷,進而被確診為自閉癥患兒。?自閉癥,又被稱作孤獨癥,廣義上...
雷蛇宣布推出靈刃 Studio版:搭載Quadro RTX 5000顯卡和優(yōu)化的新屏幕。 英偉達宣布推出最新的Quadro專業(yè)GPU之后,雷蛇正在利用這項新技術(shù),新的型號包含雷蛇靈刃 15和17 Studio Edition兩款。新的專業(yè)筆記本電腦提供了經(jīng)典的雷蛇數(shù)控機加工的銀色鋁制機殼,配備了英偉達 Quadro RTX和更高品質(zhì)的顯示器。 雷蛇靈刃 15 Studio Edition將配備UHD OL...
近些年,蘋果造車的消息不斷,日前又有重磅消息傳出,稱摩根士丹利分析師預計,蘋果今年將在汽車技術(shù)研發(fā)方面投入接近190億美元,折合人民幣超1300億。與整個汽車行業(yè)800至1000億美元的研發(fā)投入總額相比,不得不說,這是一個驚人的數(shù)字?! ≡摲治鰩熣J為,蘋果公司將汽車技術(shù)視為“一個巨大的市場”,類似于其對健康和金融技術(shù)的看法,并預測蘋...

史海拾趣

小廣播
設(shè)計資源 培訓 開發(fā)板 精華推薦

最新單片機文章

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發(fā)圈

 
機器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved