国产免费AV|泡泡玛特欧洲总部将设在伦敦|中文天堂网www新版资源在线|一本久道综合在线中文|国精产品一二三产区的使用方法|香蕉鱼在线观看|www.27eee

ELEOK

標(biāo)題: STM32狀態(tài)機(jī)思想實(shí)現(xiàn)單擊、雙擊、長(zhǎng)按 源程序 [打印本頁(yè)]

作者: 路漫漫    時(shí)間: 2020-5-30 01:34
標(biāo)題: STM32狀態(tài)機(jī)思想實(shí)現(xiàn)單擊、雙擊、長(zhǎng)按 源程序
  1. /*直接復(fù)制以下代碼,實(shí)現(xiàn)*/

  2. #include "stm32f10x.h"
  3. #include "bitband_cm3.h"
  4. #include "systick.h"
  5. #define N_key    0             //無(wú)鍵
  6. #define S_key    1             //單鍵
  7. #define D_key    2             //雙鍵
  8. #define L_key    3             //長(zhǎng)鍵
  9. #define KEY_AN (GPIOA->IDR & 1<<0)
  10. #define BEEF PCout(3)

  11. /**********************************************************************
  12. *函數(shù)名:delay_us
  13. *功  能:延遲1us
  14. *參  數(shù):us最大2^24/9=1864135us
  15. *返  回:無(wú)
  16. *備  注:無(wú)
  17. **********************************************************************/
  18. void delay_us(u16 us)
  19. {
  20.         SysTick->LOAD = us * 9;        //裝載計(jì)數(shù)值
  21.         SysTick->VAL = 0;                //清空當(dāng)前值
  22.         SysTick->CTRL |= 1;        //使能計(jì)數(shù)器
  23.         while(!(SysTick->CTRL & (1 << 16)));//等待計(jì)數(shù)結(jié)束
  24.         SysTick->CTRL &=~ 1;//關(guān)閉計(jì)數(shù)
  25. }

  26. //LED初始化
  27. void LED_Init(void)
  28. {
  29. #if 0
  30.         RCC->APB2ENR |= 3<<3;//開(kāi)啟PB/PC口時(shí)鐘
  31.         GPIOB->CRL &=~(0XF<<4*1);//清PB1
  32.         GPIOB->CRL |=(0X3<<4*1);//通用輸出 50M
  33.         GPIOC->CRL &=~(0XF<<4*5);//清PC5
  34.         GPIOC->CRL |=(0X3<<4*5);//通用輸出 50M
  35.         GPIOB->ODR |=(1<<1);//默認(rèn)給高電平,關(guān)燈,
  36.         GPIOC->ODR |=(5<<1);
  37. //        GPIOB->ODR &=~(1<<1);//點(diǎn)燈
  38. //        GPIOC->ODR &=~(5<<1);
  39.         #else  
  40.         GPIO_InitTypeDef GPIO_InitStruct;
  41.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOB,ENABLE);//開(kāi)啟PB/PC口時(shí)鐘.
  42.         GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
  43.         GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//通用推挽
  44.         GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//50M
  45.         GPIO_Init(GPIOB, &GPIO_InitStruct);//PB1
  46.         GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;
  47.         GPIO_Init(GPIOC, &GPIO_InitStruct);//PC5
  48.         GPIO_SetBits(GPIOB, GPIO_Pin_1);//默認(rèn)給高電平,關(guān)燈,不能少了這步,因?yàn)檩敵鰯?shù)據(jù)寄存器默認(rèn)值給低電平
  49.         GPIO_SetBits(GPIOC, GPIO_Pin_5);
  50. //        GPIO_ResetBits(GPIOB, GPIO_Pin_1);//開(kāi)燈
  51. //        GPIO_ResetBits(GPIOC, GPIO_Pin_5);

  52. //        PBout(1)=0;
  53. //        PCout(5)=0;
  54.         #endif
  55. }
  56. //按鍵初始化
  57. void KEY_Iint(void)
  58. {
  59.         RCC->APB2ENR |= 1<<2;//開(kāi)啟PA口時(shí)鐘
  60. }
  61. //蜂鳴器初始化
  62. void BEEF_Iint(void)
  63. {
  64.         RCC->APB2ENR |= 1<<4;//開(kāi)啟PC口時(shí)鐘
  65.         GPIOC->CRL &=~(0XF<<4*3);//清PC3
  66.         GPIOC->CRL |=(0X3<<4*3);//通用輸出 50M
  67. }


  68. /*
  69.         驅(qū)動(dòng)層
  70.         1.完成按鍵的消抖,松手檢測(cè)
  71.         2.把過(guò)程細(xì)分為一個(gè)個(gè)狀態(tài)
  72.         3.實(shí)現(xiàn)長(zhǎng)按與單擊功能

  73.         按鍵初始態(tài)
  74.         按鍵確認(rèn)態(tài)
  75.         按鍵計(jì)時(shí)態(tài)
  76.         等待按鍵釋放態(tài)
  77. */
  78. unsigned char key_driver()
  79. {
  80.     static u8 key_state = 0, key_time = 0;
  81.     u8 key_return = N_key;

  82.     switch (key_state)
  83.     {
  84.       case 0:                                      // 按鍵初始態(tài)
  85.         if (!KEY_AN) key_state = 1;         // 鍵被按下,狀態(tài)轉(zhuǎn)換到按鍵消抖和確認(rèn)狀態(tài)
  86.         break;

  87.       case 1:                                                              // 按鍵消抖與確認(rèn)態(tài)
  88.         if (!KEY_AN)
  89.         {
  90.              key_time = 0;                    
  91.              key_state = 2;                                                           // 按鍵仍然處于按下,消抖完成,狀態(tài)轉(zhuǎn)換到按下鍵時(shí)間的計(jì)時(shí)狀態(tài),但返回的還是無(wú)鍵事件
  92.         }
  93.         else
  94.              key_state = 0;                                                           // 按鍵已抬起,轉(zhuǎn)換到按鍵初始態(tài)。此處完成和實(shí)現(xiàn)軟件消抖,其實(shí)按鍵的按下和釋放都在此消抖的。
  95.         break;

  96.       case 2:                                                                                                                         // 按下鍵時(shí)間的計(jì)時(shí)狀態(tài)
  97.         if(KEY_AN)
  98.         {
  99.              key_return = S_key;                        // 此時(shí)按鍵釋放,說(shuō)明是產(chǎn)生一次短操作,回送S_key
  100.              key_state = 0;                                                           // 轉(zhuǎn)換到按鍵初始態(tài)
  101.         }
  102.         else if (++key_time >= 100)                     // 繼續(xù)按下,計(jì)時(shí)加10ms(10ms為本函數(shù)循環(huán)執(zhí)行間隔)
  103.         {
  104.              key_return = L_key;                        // 按下時(shí)間>1000ms,此按鍵為長(zhǎng)按操作,返回長(zhǎng)鍵事件
  105.              key_state = 3;                                                           // 轉(zhuǎn)換到等待按鍵釋放狀態(tài)
  106.         }
  107.         break;

  108.       case 3:                                                                          // 等待按鍵釋放狀態(tài),此狀態(tài)只返回?zé)o按鍵事件
  109.         if (KEY_AN) key_state = 0;                             // 按鍵已釋放,轉(zhuǎn)換到按鍵初始態(tài)
  110.         break;
  111.     }
  112.     return key_return;
  113. }

  114. /*
  115.         業(yè)務(wù)邏輯層
  116.         1.單擊、雙擊、長(zhǎng)按的分配
  117. */
  118. unsigned char key_read()
  119. {
  120.     static u8 key_m = 0, key_time_1 = 0;
  121.     u8 key_return = N_key,key_temp;

  122.     key_temp = key_driver();

  123.     switch(key_m)
  124.     {
  125.         case 0:
  126.             if (key_temp == S_key )
  127.             {
  128.                  key_time_1 = 0;               // 第1次單擊,不返回,到下個(gè)狀態(tài)判斷后面是否出現(xiàn)雙擊
  129.                  key_m = 1;
  130.             }
  131.             else
  132.                  key_return = key_temp;        // 對(duì)于無(wú)鍵、長(zhǎng)鍵,返回原事件
  133.             break;

  134.         case 1:
  135.             if (key_temp == S_key)             // 又一次單擊(間隔肯定<500ms)
  136.             {
  137.                  key_return = D_key;           // 返回雙擊鍵事件,回初始狀態(tài)
  138.                  key_m = 0;
  139.             }
  140.             else                                
  141.             {                                  // 這里500ms內(nèi)肯定讀到的都是無(wú)鍵事件,因?yàn)殚L(zhǎng)鍵>1000ms,在1s前低層返回的都是無(wú)鍵
  142.                  if(++key_time_1 >= 30)
  143.                  {
  144.                       key_return = S_key;      // 500ms內(nèi)沒(méi)有再次出現(xiàn)單鍵事件,返回上一次的單鍵事件
  145.                       key_m = 0;               // 返回初始狀態(tài)
  146.                  }
  147.              }
  148.              break;
  149.     }
  150.     return key_return;
  151. }

  152. /*
  153.         單擊:300ms~1000ms之間
  154.         雙擊:300ms內(nèi)
  155.         長(zhǎng)按:超過(guò)1s

  156.         單擊:控制LED1
  157.         雙擊:控制LED2
  158.         長(zhǎng)按:控制蜂鳴器
  159. */
  160. int main(void)
  161. {
  162.         LED_Init();
  163.         KEY_Iint();
  164.         BEEF_Iint();
  165.         while(1)
  166.         {
  167.                 switch(key_read())
  168.                 {
  169.                         case N_key:
  170.                                 delay_ms(10);
  171.                         break;
  172.                         case S_key:
  173.                                 PBout(1)=!PBout(1);
  174.                         break;
  175.                         case D_key:
  176.                                 PCout(5)=!PCout(5);
  177.                                 break;
  178.                         case L_key:
  179.                                 BEEF = !BEEF;
  180.                                 break;
  181.                 }
  182.         }
  183.         return 0;
  184. }
復(fù)制代碼







歡迎光臨 ELEOK (http://m.afoofa.cn/) Powered by Discuz! X5.0