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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6036|回復: 10
打印 上一主題 下一主題
收起左側

STM32狀態機思想實現單擊、雙擊、長按 源程序

  [復制鏈接]
跳轉到指定樓層
樓主
ID:763998 發表于 2020-5-29 09:35 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
/*直接復制以下代碼,實現,自己在獨立研究吸收*/


#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)

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

//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);//默認給高電平,關燈,不能少了這步,因為輸出數據寄存器默認值給低電平
        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.把過程細分為一個個狀態
        3.實現長按與單擊功能

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

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

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

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

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

/*
        業務邏輯層
        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次單擊,不返回,到下個狀態判斷后面是否出現雙擊
                 key_m = 1;
            }
            else
                 key_return = key_temp;        // 對于無鍵、長鍵,返回原事件
            break;

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


評分

參與人數 3黑幣 +68 收起 理由
AAA_MCU + 12 很給力!
hzd530 + 6
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏19 分享淘帖 頂2 踩
回復

使用道具 舉報

沙發
ID:85865 發表于 2020-6-28 08:17 | 只看該作者
這個可以有
回復

使用道具 舉報

板凳
ID:763998 發表于 2020-6-28 09:22 | 只看該作者

哈哈哈,差點失去發帖的動力,幸好有你
回復

使用道具 舉報

地板
ID:790159 發表于 2020-6-29 10:18 | 只看該作者
已學習 ,感謝樓主分享
回復

使用道具 舉報

5#
ID:82098 發表于 2021-4-25 20:13 | 只看該作者
四個按鍵如何處理?敬請指教!
回復

使用道具 舉報

6#
ID:519089 發表于 2021-7-14 21:06 | 只看該作者
學習了,,,支持原創
回復

使用道具 舉報

7#
ID:584195 發表于 2021-11-15 18:22 | 只看該作者
可以帶我寫指針函數的寫法嗎?
回復

使用道具 舉報

8#
ID:809754 發表于 2022-8-5 16:23 | 只看該作者
很多按鍵呢  怎么搞
回復

使用道具 舉報

9#
ID:165291 發表于 2022-11-14 20:08 | 只看該作者
多按鍵有必要這么寫么?
回復

使用道具 舉報

10#
ID:52721 發表于 2023-1-11 11:10 | 只看該作者
對于單鍵而言,是個很不錯的選擇。
回復

使用道具 舉報

11#
ID:890367 發表于 2023-1-11 18:24 來自手機 | 只看該作者
多按鍵呢
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产福利视频导航 | 国内91在线 | 亚洲精品女人久久久 | 成人深夜福利 | 日韩亚洲一区二区 | 日韩不卡一区二区 | 日本一区二区高清不卡 | 日韩和的一区二区 | 久久久精品一区二区三区 | 午夜影院网站 | 日韩欧美国产一区二区三区 | 日日操操| 99爱在线视频 | 国产在线91 | 国产精品成人一区二区三区 | 久久久久国产精品午夜一区 | 毛片av免费在线观看 | 一区二区三区欧美在线观看 | 久久久激情 | 欧美专区日韩 | 一级片视频免费观看 | 大陆一级毛片免费视频观看 | 国产精品一区一区 | 国产精品一区网站 | 国产在线视频一区二区 | 亚洲国产精品一区二区第一页 | 久久亚洲国产 | 人妖av| 少妇一区在线观看 | 99久久久久 | 美女福利视频网站 | 国产视频线观看永久免费 | 请别相信他免费喜剧电影在线观看 | 日韩欧美福利视频 | 97日韩精品 | 亚洲国产成人精品在线 | 午夜视频免费 | 免费看淫片 | 久久久国产一区二区三区 | 欧美αv | 亚洲综合色网 |