久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

標題: STM32狀態(tài)機思想實現(xiàn)單擊、雙擊、長按 源程序 [打印本頁]

作者: 小小涼冰樂    時間: 2020-5-29 09:35
標題: STM32狀態(tài)機思想實現(xiàn)單擊、雙擊、長按 源程序
/*直接復制以下代碼,實現(xiàn),自己在獨立研究吸收*/


#include "stm32f10x.h"
#include "bitband_cm3.h"
#include "systick.h"
#define N_key    0             //無鍵
#define S_key    1             //單鍵
#define D_key    2             //雙鍵
#define L_key    3             //長鍵
#define KEY_AN (GPIOA->IDR & 1<<0)
#define BEEF PCout(3)

/**********************************************************************
*函數(shù)名:delay_us
*功  能:延遲1us
*參  數(shù):us最大2^24/9=1864135us
*返  回:無
*備  注:無
**********************************************************************/
void delay_us(u16 us)
{
        SysTick->LOAD = us * 9;        //裝載計數(shù)值
        SysTick->VAL = 0;                //清空當前值
        SysTick->CTRL |= 1;        //使能計數(shù)器
        while(!(SysTick->CTRL & (1 << 16)));//等待計數(shù)結束
        SysTick->CTRL &=~ 1;//關閉計數(shù)
}

//LED初始化
void LED_Init(void)
{
#if 0
        RCC->APB2ENR |= 3<<3;//開啟PB/PC口時鐘
        GPIOB->CRL &=~(0XF<<4*1);//清PB1
        GPIOB->CRL |=(0X3<<4*1);//通用輸出 50M
        GPIOC->CRL &=~(0XF<<4*5);//清PC5
        GPIOC->CRL |=(0X3<<4*5);//通用輸出 50M
        GPIOB->ODR |=(1<<1);//默認給高電平,關燈,
        GPIOC->ODR |=(5<<1);
//        GPIOB->ODR &=~(1<<1);//點燈
//        GPIOC->ODR &=~(5<<1);
        #else  
        GPIO_InitTypeDef GPIO_InitStruct;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOB,ENABLE);//開啟PB/PC口時鐘.
        GPIO_InitStruct.GPIO_Pin=GPIO_Pin_1;
        GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//通用推挽
        GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//50M
        GPIO_Init(GPIOB, &GPIO_InitStruct);//PB1
        GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;
        GPIO_Init(GPIOC, &GPIO_InitStruct);//PC5
        GPIO_SetBits(GPIOB, GPIO_Pin_1);//默認給高電平,關燈,不能少了這步,因為輸出數(shù)據(jù)寄存器默認值給低電平
        GPIO_SetBits(GPIOC, GPIO_Pin_5);
//        GPIO_ResetBits(GPIOB, GPIO_Pin_1);//開燈
//        GPIO_ResetBits(GPIOC, GPIO_Pin_5);

//        PBout(1)=0;
//        PCout(5)=0;
        #endif
}
//按鍵初始化
void KEY_Iint(void)
{
        RCC->APB2ENR |= 1<<2;//開啟PA口時鐘
}
//蜂鳴器初始化
void BEEF_Iint(void)
{
        RCC->APB2ENR |= 1<<4;//開啟PC口時鐘
        GPIOC->CRL &=~(0XF<<4*3);//清PC3
        GPIOC->CRL |=(0X3<<4*3);//通用輸出 50M
}


/*
        驅動層
        1.完成按鍵的消抖,松手檢測
        2.把過程細分為一個個狀態(tài)
        3.實現(xiàn)長按與單擊功能

        按鍵初始態(tài)
        按鍵確認態(tài)
        按鍵計時態(tài)
        等待按鍵釋放態(tài)
*/
unsigned char key_driver()
{
    static u8 key_state = 0, key_time = 0;
    u8 key_return = N_key;

    switch (key_state)
    {
      case 0:                                      // 按鍵初始態(tài)
        if (!KEY_AN) key_state = 1;         // 鍵被按下,狀態(tài)轉換到按鍵消抖和確認狀態(tài)
        break;

      case 1:                                                              // 按鍵消抖與確認態(tài)
        if (!KEY_AN)
        {
             key_time = 0;                    
             key_state = 2;                                                           // 按鍵仍然處于按下,消抖完成,狀態(tài)轉換到按下鍵時間的計時狀態(tài),但返回的還是無鍵事件
        }
        else
             key_state = 0;                                                           // 按鍵已抬起,轉換到按鍵初始態(tài)。此處完成和實現(xiàn)軟件消抖,其實按鍵的按下和釋放都在此消抖的。
        break;

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

      case 3:                                                                          // 等待按鍵釋放狀態(tài),此狀態(tài)只返回無按鍵事件
        if (KEY_AN) key_state = 0;                             // 按鍵已釋放,轉換到按鍵初始態(tài)
        break;
    }
    return key_return;
}

/*
        業(yè)務邏輯層
        1.單擊、雙擊、長按的分配
*/
unsigned char key_read()
{
    static u8 key_m = 0, key_time_1 = 0;
    u8 key_return = N_key,key_temp;

    key_temp = key_driver();

    switch(key_m)
    {
        case 0:
            if (key_temp == S_key )
            {
                 key_time_1 = 0;               // 第1次單擊,不返回,到下個狀態(tài)判斷后面是否出現(xiàn)雙擊
                 key_m = 1;
            }
            else
                 key_return = key_temp;        // 對于無鍵、長鍵,返回原事件
            break;

        case 1:
            if (key_temp == S_key)             // 又一次單擊(間隔肯定<500ms)
            {
                 key_return = D_key;           // 返回雙擊鍵事件,回初始狀態(tài)
                 key_m = 0;
            }
            else                                
            {                                  // 這里500ms內肯定讀到的都是無鍵事件,因為長鍵>1000ms,在1s前低層返回的都是無鍵
                 if(++key_time_1 >= 30)
                 {
                      key_return = S_key;      // 500ms內沒有再次出現(xiàn)單鍵事件,返回上一次的單鍵事件
                      key_m = 0;               // 返回初始狀態(tài)
                 }
             }
             break;
    }
    return key_return;
}

/*
        單擊:300ms~1000ms之間
        雙擊:300ms內
        長按:超過1s

        單擊:控制LED1
        雙擊:控制LED2
        長按:控制蜂鳴器
*/
int main(void)
{
        LED_Init();
        KEY_Iint();
        BEEF_Iint();
        while(1)
        {
                switch(key_read())
                {
                        case N_key:
                                delay_ms(10);
                        break;
                        case S_key:
                                PBout(1)=!PBout(1);
                        break;
                        case D_key:
                                PCout(5)=!PCout(5);
                                break;
                        case L_key:
                                BEEF = !BEEF;
                                break;
                }
        }
        return 0;
}



作者: 252622979    時間: 2020-6-28 08:17
這個可以有
作者: 小小涼冰樂    時間: 2020-6-28 09:22
252622979 發(fā)表于 2020-6-28 08:17
這個可以有

哈哈哈,差點失去發(fā)帖的動力,幸好有你
作者: cdlongbo    時間: 2020-6-29 10:18
已學習 ,感謝樓主分享
作者: zlkj    時間: 2021-4-25 20:13
四個按鍵如何處理?敬請指教!
作者: 單片機愛好者223    時間: 2021-7-14 21:06
學習了,,,支持原創(chuàng)
作者: zyluglugl    時間: 2021-11-15 18:22
可以帶我寫指針函數(shù)的寫法嗎?
作者: 運氣仙君    時間: 2022-8-5 16:23
很多按鍵呢  怎么搞

作者: timeabcd    時間: 2022-11-14 20:08
多按鍵有必要這么寫么?
作者: cjl519    時間: 2023-1-11 11:10
對于單鍵而言,是個很不錯的選擇。
作者: wys950215    時間: 2023-1-11 18:24
多按鍵呢




歡迎光臨 (http://www.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 精品欧美视频 | 亚洲 欧美 日韩在线 | 成人国内精品久久久久一区 | 国产一区免费视频 | 在线欧美亚洲 | 91精品国产一二三 | 日韩一区不卡 | 91视频免费视频 | 精品国产欧美一区二区三区不卡 | 999www视频免费观看 | 亚洲精彩视频在线观看 | 一区二区三区高清 | 国产1区在线 | 超碰综合 | 99精品免费视频 | 国产精品欧美一区二区三区 | 涩涩视频大全 | 中文av字幕 | 福利视频1000 | 久久久久久久久久久久久久av | 国产一级淫片免费视频 | 91欧美精品成人综合在线观看 | 成人深夜福利 | 亚洲在线观看视频 | 精品久久久久久久久久久久久久 | 精品久久久久久久久久久院品网 | 精品欧美一区免费观看α√ | 日韩中文字幕在线不卡 | 欧美不卡网站 | 日本在线播放 | 请别相信他免费喜剧电影在线观看 | 一区二区三区影院 | 日韩一区二区三区在线 | 一区二区不卡高清 | 亚洲精品久久久久久久不卡四虎 | 日韩欧美一级精品久久 | 国产精品电影网 | 久久美国 | 国产在线激情视频 | 亚洲精品自在在线观看 | 国产东北一级毛片 |