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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4884|回復(fù): 22
收起左側(cè)

標(biāo)準(zhǔn)的單片機(jī)C語言按鍵檢測代碼格式是什么樣的?

  [復(fù)制鏈接]
ID:709761 發(fā)表于 2022-5-16 11:41 | 顯示全部樓層 |閱讀模式
//以下兩種單片機(jī)C語言代碼,哪個正確

if(k1 == 0)
  {
                Delay6ms();//按鍵消抖
                if(k1 == 0)
                {

                //執(zhí)行按鍵結(jié)果
               }
                while(!k1)//等待按鍵放開
   }

//--------------------------------------------------------

if(k1 == 0)
  {
                Delay6ms();//按鍵消抖
                if(k1 == 0)
                {

                //執(zhí)行按鍵結(jié)果

                while(!k1)//等待按鍵放開
                }  
            }

回復(fù)

使用道具 舉報(bào)

ID:276663 發(fā)表于 2022-5-16 13:09 | 顯示全部樓層
回復(fù)

使用道具 舉報(bào)

ID:161164 發(fā)表于 2022-5-16 13:17 | 顯示全部樓層
都不好,浪費(fèi)資源

  1. static uint Delay = 0;

  2. if(K1 == 0)

  3. {

  4. if(Delay <= 0xFFFF)Delay++;

  5. if(Delay == 1000)

  6. {

  7. //執(zhí)行按鍵結(jié)果

  8. }

  9. }else{

  10. Delay=0;

  11. }
復(fù)制代碼




回復(fù)

使用道具 舉報(bào)

ID:56665 發(fā)表于 2022-5-16 13:47 | 顯示全部樓層
lkc8210 發(fā)表于 2022-5-16 13:17
都不好,浪費(fèi)資源

這個代碼和上面的沒有區(qū)別,Delay++一樣在空耗,要想不浪費(fèi)資源,延時放在定時器中斷里處理。
回復(fù)

使用道具 舉報(bào)

ID:123289 發(fā)表于 2022-5-16 14:01 | 顯示全部樓層
都不標(biāo)準(zhǔn),贊同地板的說法。
回復(fù)

使用道具 舉報(bào)

ID:213173 發(fā)表于 2022-5-16 14:30 | 顯示全部樓層
沒有標(biāo)準(zhǔn)的按鍵代碼。用什么方式寫按鍵代碼是設(shè)計(jì)者根據(jù)硬件條件、應(yīng)用場景和編程習(xí)慣所采用。最常見的代碼不下20種。樓主所列兩種其實(shí)就是同為一種最低水平的入門級寫法,大多見于針對初學(xué)者的教材中。優(yōu)點(diǎn)是初學(xué)者容易讀懂,用于極簡單的程序也無不可。其缺點(diǎn)是效率低下,與其它需要快速響應(yīng)的程序發(fā)生沖突.....。
回復(fù)

使用道具 舉報(bào)

ID:161164 發(fā)表于 2022-5-16 14:38 | 顯示全部樓層
m182892 發(fā)表于 2022-5-16 13:47
這個代碼和上面的沒有區(qū)別,Delay++一樣在空耗,要想不浪費(fèi)資源,延時放在定時器中斷里處理。

一個Delay++的消耗比的上Delay6ms和while(!k1)的死等?
我的代碼的原理是定時掃描按鍵的電平
確保按鍵保持低電平一段時間才輸出
每掃描一次
if(K1==0)
if(Delay<0xFFFF)
Delay++;
if(Delay==1000)
這四句只用了5.43us(keil debug mode STC89C52RC@11.0592)

求問有沒有更低消耗的消抖算法
回復(fù)

使用道具 舉報(bào)

ID:624769 發(fā)表于 2022-5-16 16:06 來自手機(jī) | 顯示全部樓層
lkc8210 發(fā)表于 2022-5-16 14:38
一個Delay++的消耗比的上Delay6ms和while(!k1)的死等?
我的代碼的原理是定時掃描按鍵的電平
確保按鍵保 ...

發(fā)現(xiàn)你特別不愛用中斷。
誠然,表面上看,你這段代碼的確只需要5.4us,比起阻塞式while,的確不耗系統(tǒng)資源,但是,你累加1000次,才完成一次按鍵判斷,總共耗費(fèi)的系統(tǒng)資源,并不比delay6ms節(jié)約吧? 隨著你程序復(fù)雜度的提升,你要不停地修正1000這個值,來均衡消抖和漏判這個平衡點(diǎn)。某種意義上來講,穩(wěn)定性還不如阻塞式判斷。用個中斷不好么?硬件放在那里不用,才是真正的浪費(fèi),并不是節(jié)約。真要效率最大化,個人覺得,外部中斷觸發(fā),定時器中斷消抖,才是最優(yōu)方案,系統(tǒng)中斷資源不夠了,再去考慮不用中斷的方法。
回復(fù)

使用道具 舉報(bào)

ID:203661 發(fā)表于 2022-5-16 16:22 | 顯示全部樓層
你那個是標(biāo)準(zhǔn)教科書寫法
回復(fù)

使用道具 舉報(bào)

ID:213173 發(fā)表于 2022-5-16 16:43 | 顯示全部樓層
本帖最后由 wulin 于 2022-5-16 17:21 編輯
lkc8210 發(fā)表于 2022-5-16 14:38
一個Delay++的消耗比的上Delay6ms和while(!k1)的死等?
我的代碼的原理是定時掃描按鍵的電平
確保按鍵保 ...

“這四句只用了5.43us”不如 if(K1==0){if(++Delay>=1000).....} 效率更高。常見的按鍵多為選用輕觸開關(guān),其抖動時間在2~10ms范圍。5.43us的時間難以確保避開抖動時段。在特定的應(yīng)用場景,消抖不是必須的。諸如某大佬的經(jīng)典代碼,完成長短按就三條語句。
unsigned char Trg;
unsigned char Cont;
void KeyRead( void )
{
    unsigned char ReadData = PINB^0xff;
    Trg = ReadData & (ReadData ^ Cont);
    Cont = ReadData;
}
回復(fù)

使用道具 舉報(bào)

ID:161164 發(fā)表于 2022-5-16 16:46 | 顯示全部樓層
188610329 發(fā)表于 2022-5-16 16:06
發(fā)現(xiàn)你特別不愛用中斷。
誠然,表面上看,你這段代碼的確只需要5.4us,比起阻塞式while,的確不耗系統(tǒng)資 ...

大佬你好

我沒說不用中斷啊~
如果把代碼放到1ms中斷中
直接寫個if(Delay==20)就可以濾掉99.99%的抖動而不用調(diào)節(jié)
Delay更可以改用unsigned char更節(jié)約步驟

我是考慮到有些新手還沒學(xué)定時器中斷
就推薦一個低消耗,不阻塞,可以不用定時器中斷,簡單易懂的按鍵消抖代碼

至于關(guān)于累積消耗,我更考慮每次大循環(huán)的消耗
經(jīng)常有貼子求問按鍵令數(shù)碼管閃爍
就是一些新手用了delayms和while(!K1)這種阻塞式消抖

比起突然來個大消耗,我更愿意選連續(xù)而均勻的小消耗

更正:
之前說的5.43 us消耗是沒有鍵按時的計(jì)時
有按鍵時是17.36 us(keil debug mode STC89C52RC@11.0592)
回復(fù)

使用道具 舉報(bào)

ID:161164 發(fā)表于 2022-5-16 17:11 | 顯示全部樓層
wulin 發(fā)表于 2022-5-16 16:43
“這四句只用了5.43us”和只用一句if(K1==0)沒有什么區(qū)別。常見的按鍵多為選用輕觸開關(guān),其抖動時間在2~1 ...

大佬你好

之前我仿真錯了
5.43 us是沒有鍵按時的耗時
有按鍵時是17.36 us

如果是if(Delay == 1)當(dāng)然沒有用
但用的是if(Delay == 1000)在只計(jì)算自己的耗時都有17.36ms
足以濾掉99.99%的抖動

我也知道消抖不是必須的
如一些有自保的開關(guān),限位器等
按著就是按著
不用理會按了多少下

那大佬的代碼我也拜讀過
第一次看時驚為天人
連說三字妙妙妙
我只知道他可以檢測電平的改變來觸發(fā)短按
但如何觸發(fā)長按。。。愿聞其詳
回復(fù)

使用道具 舉報(bào)

ID:213173 發(fā)表于 2022-5-16 17:38 | 顯示全部樓層
lkc8210 發(fā)表于 2022-5-16 17:11
大佬你好

之前我仿真錯了

不好意思,只看了前面“這四句只用了5.43us”就望文生義,確為不妥,帖子已改。長短按就三條語句是真是的。我特別強(qiáng)調(diào)的是應(yīng)用場景。 一款精巧的按鍵處理程序.doc (36.5 KB, 下載次數(shù): 13)
回復(fù)

使用道具 舉報(bào)

ID:624769 發(fā)表于 2022-5-17 14:52 | 顯示全部樓層
lkc8210 發(fā)表于 2022-5-16 16:46
大佬你好

我沒說不用中斷啊~

抱歉,沒有別的意思,就是看過不少你的回帖,發(fā)現(xiàn)你大多都刻意的回避使用中斷,之前,也看了你關(guān)于旋轉(zhuǎn)編碼器的一個回帖(構(gòu)思很好,非常簡潔,但是,因?yàn)榭桃饣乇苤袛啵杂新┒矗?dāng)然普通使用是沒有什么問題的,這里就不展開了),而此帖,樓主又刻意強(qiáng)調(diào)“標(biāo)準(zhǔn)”二字,雖然按鍵判斷,沒有幾百種都有幾十種方式,但是,要說標(biāo)準(zhǔn)的話,排除衍生出來的組合按鍵,矩陣按鍵不說,比較有代表性的獨(dú)立按鍵而言,用外部中斷判斷,才是能算比較“標(biāo)準(zhǔn)”的用法吧?
“標(biāo)準(zhǔn)”按鍵,應(yīng)該硬件消抖,算了,標(biāo)準(zhǔn)是被不斷的拉低的,就當(dāng)是軟件消抖是“標(biāo)準(zhǔn)”吧。竊以為,外部中斷+定時器中斷,占用系統(tǒng)少。無漏判誤判,歡迎指正。

bit    Key_Press;
void main()
{
       TMOD = 0x00;            //13位定時器模式 (不設(shè)初值,就用從默認(rèn)的 0 開始計(jì)時 12Mhz 約 8.192Ms 溢出)
       IT0 = 1;               //下降沿觸發(fā)
       EX0 = 1;
       ET0 = 1;
       EA  = 1;
       while(1)
       {
                if(Key_Press)
                {
                        Key_Press = 0;   //清按鍵標(biāo)志
                        //按鍵后需要執(zhí)行的代碼。
                }
       }
}

void EX0_INT  interrupt 0
{
        Key_Press = 1;    //置位按鍵標(biāo)志
        EX0 = 0;       //關(guān)外部中斷
        TR0 = 1;        //開定時器消抖
}

void T0_INT  interrupt 1
{
        if(IE0)
        {
               IE0 = 0;   //繼續(xù)消抖
        }
        else
        {
               EX0 = 1;   //消抖完成,重開外部中斷
               TR0 = 0;  //關(guān)定時器
        }
}
回復(fù)

使用道具 舉報(bào)

ID:883242 發(fā)表于 2022-5-17 15:16 | 顯示全部樓層
lkc8210 發(fā)表于 2022-5-16 17:11
大佬你好

之前我仿真錯了

新開關(guān)一般不需要消抖,但是用舊了一般都會抖。

曾經(jīng)遇到過一個水平挺高的高手,居然跟我說按鍵不需要消抖,后來聽熟悉他的人說,畢業(yè)之后只做過單片機(jī)原廠FAE,給要用單片機(jī)的廠家做個demo就行了,從來沒有做過一個產(chǎn)品的全壽命周期測試。然后我就找了幾個新按鍵,果然一個抖的都沒有。
回復(fù)

使用道具 舉報(bào)

ID:824490 發(fā)表于 2022-5-17 17:35 | 顯示全部樓層
Hephaestus 發(fā)表于 2022-5-17 15:16
新開關(guān)一般不需要消抖,但是用舊了一般都會抖。

曾經(jīng)遇到過一個水平挺高的高手,居然跟我說按鍵不需要 ...

這里的“抖”不一定是按鍵產(chǎn)生的,還可能是外部電磁環(huán)境產(chǎn)生的尖脈沖。。
回復(fù)

使用道具 舉報(bào)

ID:161164 發(fā)表于 2022-5-17 17:40 | 顯示全部樓層
wulin 發(fā)表于 2022-5-16 17:38
不好意思,只看了前面“這四句只用了5.43us”就望文生義,確為不妥,帖子已改。長短按就三條語句是真是的 ...

文件收藏了,感謝分享
回復(fù)

使用道具 舉報(bào)

ID:161164 發(fā)表于 2022-5-17 17:48 | 顯示全部樓層
188610329 發(fā)表于 2022-5-17 14:52
抱歉,沒有別的意思,就是看過不少你的回帖,發(fā)現(xiàn)你大多都刻意的回避使用中斷,之前,也看了你關(guān)于旋轉(zhuǎn)編 ...

代碼很巧妙,但為了一個按鍵占用了一個外中斷和一個定時器,算不上占用系統(tǒng)少吧?
而且只能濾掉按下那一剎那的抖動,濾不掉放開那一剎那的抖動吧?
稍微修改一下
  1. bit    Key_Press;
  2. sbit Key_XX = P3^2;
  3. void main()
  4. {
  5.         TMOD = 0x00;            //13位定時器模式 (不設(shè)初值,就用從默認(rèn)的 0 開始計(jì)時 12Mhz 約 8.192Ms 溢出)
  6.         IT0 = 1;               //下降沿觸發(fā)
  7.         EX0 = 1;
  8.         ET0 = 1;
  9.         EA  = 1;
  10.         while(1)
  11.         {
  12.                 if(Key_Press)
  13.                 {
  14.                         Key_Press = 0;   //清按鍵標(biāo)志
  15.                         //按鍵后需要執(zhí)行的代碼。
  16.                 }
  17.         }
  18. }

  19. void EX0_INT  interrupt 0
  20. {
  21.         EX0 = 0;       //關(guān)外部中斷
  22.         TR0 = 1;        //開定時器消抖
  23. }

  24. void T0_INT  interrupt 1
  25. {
  26.         if(IE0)
  27.         {
  28.                 IE0 = 0;   //繼續(xù)消抖
  29.         }
  30.         else
  31.         {
  32.                 if(!Key_XX)Key_Press = 1;    //置位按鍵標(biāo)志
  33.                 EX0 = 1;   //消抖完成,重開外部中斷
  34.                 TR0 = 0;  //關(guān)定時器
  35.         }
  36. }
復(fù)制代碼

回復(fù)

使用道具 舉報(bào)

ID:509408 發(fā)表于 2022-5-17 17:55 | 顯示全部樓層
void CheckSwitchKey(void)
{
               
                if(cgCheckSwitchTime<3)          //3ms掃描一次,該變量可放入定時器中累加
                         return;       
                //檢查前先將該IO口線設(shè)置為1
                SWITCH_KEY1 = 1;
                SWITCH_KEY2 = 1;
                cgCheckSwitchTime = 0;
                       
                if( (cgSwitchStatus & 0x01) && (SWITCH_KEY2==0) )
                {
                        //按鍵前狀態(tài)=1,目前狀態(tài)=0        (首次檢測按鍵按下)
                        cglowVotTime = 0;          //按鍵低電平計(jì)時清0
                }
                else
                {
                        if( ((cgSwitchStatus & 0x01)!=0x01) && (SWITCH_KEY2==1) )
                        {
                                //按鍵前狀態(tài)=0,目前狀態(tài)=1         (按鍵彈起)
                                //低電平時間>5ms 執(zhí)行按鍵消息函數(shù)
                                if(cglowVotTime>5)                 DealKeyInfo();
                        }
                }
               
#if 0          //狀態(tài)機(jī)寫法
                switch(state)
                 {
                        case S0://狀態(tài)0        等待按鍵按下
                                if(bgStatusofKey1==0)
                                        state = S1;                //判斷輸入是否為0,為0轉(zhuǎn)入狀態(tài)1       
                                break;

                        case S1://狀態(tài)1        按鍵按下
                                if(bgStatusofKey1)
                                        state = S0;                //按鍵彈起? 返回狀態(tài)0(按鍵狀態(tài)不穩(wěn)定)       
                                else{                                //否則開始計(jì)時,轉(zhuǎn)入狀態(tài)2
                                        state =        S2;
                                        cgPushKeyTime = 0;
                                }break;
                                       
                        case S2://狀態(tài)2        等待短按釋放
                                if(bgStatusofKey1){

                                        state = S0;                        //按鍵彈起?返回狀態(tài)0(短按鍵釋放)
                                        bgEv1527Study = 0;
                                        cgFlagBeacon = 0x01;
                                        DealKeyInfo();
                                }
                                else if(cgPushKeyTime>250){ //長按超時?(1s以上)
                                        cgPushKeyTime = 0;
                                        bgEv1527Study = 1;                 //學(xué)習(xí)狀態(tài)。
                                        cgFlagBeacon = 0x02;
                                        DealKeyInfo();
                                        state=S3;                        //否則開始計(jì)時,計(jì)時結(jié)束轉(zhuǎn)入狀態(tài)3
                                }break;
                                               
                        case S3://狀態(tài)3        等待長按釋放
                                if(bgStatusofKey1)                 //長按鍵釋放?返回狀態(tài)0
                                        state=S0;               
                                else if(++cgPushKeyTime==5)        //否則開始計(jì)時,計(jì)時結(jié)束按鍵連擊
                                {
                                        cgPushKeyTime=0;
                                        /*連擊處理函數(shù)*/
                                }break;
                                       
                        default:
                                break;                                                       
                }
#endif
                //備份按鍵口線狀態(tài)
                bgStatusofKey1 = SWITCH_KEY1;

                if(SWITCH_KEY2==1)   
                        cgSwitchStatus |= 0x01;
                else
                        cgSwitchStatus &= 0xfe;
       
}
回復(fù)

使用道具 舉報(bào)

ID:624769 發(fā)表于 2022-5-17 18:19 | 顯示全部樓層
lkc8210 發(fā)表于 2022-5-17 17:48
代碼很巧妙,但為了一個按鍵占用了一個外中斷和一個定時器,算不上占用系統(tǒng)少吧?
而且只能濾掉按下那一 ...

跟你交流很開心, 以下純粹探討. 如有空盼回。

為了一個按鍵占用了一個外中斷和一個定時器,算不上占用系統(tǒng)少吧?
我還是那句話,如果中斷空著不用,嚴(yán)格意義上來講,不是節(jié)約資源,而是資源浪費(fèi),而且外部中斷判斷按鍵的話,按鍵未按下時,在主循環(huán)中,連1個時鐘的系統(tǒng)時鐘都不會占用,這還不算占用系統(tǒng)資源少么?

只能濾掉按下那一剎那的抖動,濾不掉放開那一剎那的抖動吧?
是的,實(shí)際上,我自己寫的代碼,不是這樣的,發(fā)上來的時候精簡了一下,正常自己使用的時候,主程序也不會有按鍵標(biāo)志判斷的,代碼如下:
(另,個人愛好,非工作,所以沒有測試設(shè)備,大多功能都是自己寫代碼燒錄,然后通過LED狀態(tài)來測試驗(yàn)證,你這邊方便的話可幫忙測試,實(shí)際應(yīng)用中STC15以上系列,IT0 =1 時,釋放按鍵時,只要不是故意手抖,抖不出IE0=1, 即不會觸發(fā)中斷,原因不明,可能和 IT0 的判定變更了有關(guān),你那邊有條件的話,不知能否也幫忙驗(yàn)證一下?)

void EX0_INT  interrupt 0
{
         EX0 = 0;       //關(guān)外部中斷
        TR0 = 1;        //開定時器消抖

        //此處按鍵按下后的  需要執(zhí)行的操作
}


sbit  INT0 = P3^2;
void T0_INT  interrupt 1
{
         if((IE0) || (!INT0))    //判斷按鍵釋放&消抖
        {
                IE0 = 0;   //繼續(xù)消抖
        }
         else
         {
                EX0 = 1;   //消抖完成,重開外部中斷
               TR0 = 0;  //關(guān)定時器
        }
}
回復(fù)

使用道具 舉報(bào)

ID:1026496 發(fā)表于 2022-5-17 21:34 | 顯示全部樓層
不是是這樣的,標(biāo)準(zhǔn)的是沒有阻塞的也就是沒有while(!key); 標(biāo)準(zhǔn)的就是一個函數(shù)返回鍵值根據(jù)當(dāng)前的io 的狀態(tài)返回時按鍵值;延時用定時器的tick +狀態(tài)機(jī)實(shí)現(xiàn)
回復(fù)

使用道具 舉報(bào)

ID:161164 發(fā)表于 2022-5-18 10:54 | 顯示全部樓層
188610329 發(fā)表于 2022-5-17 18:19
跟你交流很開心, 以下純粹探討. 如有空盼回。

為了一個按鍵占用了一個外中斷和一個定時器,算不上占用 ...

看大佬的貼子和回貼我也學(xué)到很多東西
特別是STC EEPROM 的操作

有時間我會試一試放手進(jìn)中斷的情況
回復(fù)

使用道具 舉報(bào)

ID:491577 發(fā)表于 2022-5-18 12:37 | 顯示全部樓層
這是標(biāo)準(zhǔn)菜鳥寫法,等到不用    Delay6ms(); while(!k1)這兩個語句也可以寫出按鍵程序的時候才算入門啦
回復(fù)

使用道具 舉報(bào)

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

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 在线激情视频 | 三级视频在线观看 | 黄频免费 | 久久久久久免费精品一区二区三区 | 日韩伦理一区二区 | 亚洲在线一区 | 中文字幕一区二区三区精彩视频 | 婷婷色在线 | 亚洲精品色 | 久久不卡日韩美女 | 欧美一级α片 | 激情五月婷婷综合 | 国产在线一区二区三区 | 日韩成人在线播放 | 久久久噜噜噜久久中文字幕色伊伊 | 黄色大片在线视频 | 亚洲传媒在线 | 国产目拍亚洲精品99久久精品 | 黑人性hd| 欧美二区三区 | 国产成人精品久久二区二区 | 成人免费在线观看 | 在线超碰 | 精品在线播放 | 欧美三区| 亚洲一区二区三区在线播放 | 日韩在线观看中文字幕 | 日韩在线欧美 | 国产激情一区二区三区 | 青青久久久 | 黄色欧美大片 | 亚洲一区视频在线 | 亚洲精品在线91 | 中文字幕第九页 | 在线视频中文字幕 | 欧美亚洲国产一区二区三区 | 人人做人人澡人人爽欧美 | 一级毛片在线看 | 一区二区在线免费观看视频 | 久久国产精品无码网站 | 欧美激情国产精品 |