找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 2646|回復(fù): 15
打印 上一主題 下一主題
收起左側(cè)

AVR單片機(jī)按鍵消抖程序問(wèn)題請(qǐng)教

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:881204 發(fā)表于 2021-8-23 17:19 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
大佬們好!我用ATTINY24A做一個(gè)按鍵控制IO輸出的功能。
原理圖如下:

目前的問(wèn)題是:
1、我的按鍵消抖好像沒作用(調(diào)不同的DELAY時(shí)間,有變化,但不解決問(wèn)題)
2、在我PA0按鍵按下不松手時(shí)(也就是按鍵輸入一直為0)。這個(gè)時(shí)候,PB1口輸出為0.4V,只有我松開按鍵以后,PB1口才會(huì)變?yōu)?V或3.3V。
原代碼如下:
#include <avr/io.h>
void delay (unsigned int ms);
int main(void)
{
        unsigned char temp=0;
        while(1)
        {
                temp = (PINA & (_BV(DDA0)));  //KEY
        if (!temp)
        {
                delay(200);
                        if(!temp)
                        {
                         DDRB = 0x0F;
                         PORTB = 0x00;
                        }
        }
                                temp = (PINA & (_BV(DDA0))); //KEY
                                if (!temp)
                                {
                                delay(200);
                                        if(!temp)
                                        {
                                        DDRB = 0x0F;
                                        PORTB = 0x02;
                                        }
                                }
        }
          return 0;
}

void delay (unsigned int ms)
        {
                unsigned int i,j;
                for(i=0;i<ms;i++)
                {
                        for(j=0;j<1000;j++);
                }
        }


請(qǐng)各位大佬幫忙看看是什么問(wèn)題,謝謝!
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:752974 發(fā)表于 2021-8-24 08:20 | 只看該作者
按鍵消抖常用的兩種方法,電容濾波,軟件延時(shí)。和什么單片機(jī)無(wú)關(guān)。
回復(fù)

使用道具 舉報(bào)

板凳
ID:881204 發(fā)表于 2021-8-25 09:12 | 只看該作者
munuc_w 發(fā)表于 2021-8-24 08:20
按鍵消抖常用的兩種方法,電容濾波,軟件延時(shí)。和什么單片機(jī)無(wú)關(guān)。

大佬好,是和什么單片機(jī)沒關(guān)系,我只是想把我遇到的問(wèn)題情況說(shuō)的全面一點(diǎn),并不是說(shuō)和單片機(jī)有關(guān)。
我發(fā)了原代碼,也就是想請(qǐng)大佬們幫我看看有什么問(wèn)題。
謝謝指導(dǎo)!
回復(fù)

使用道具 舉報(bào)

地板
ID:161164 發(fā)表于 2021-8-25 09:56 | 只看該作者
不明白你的代碼為什么要這樣寫
根據(jù)你的代碼,當(dāng)按下PA0時(shí)
PB1會(huì)產(chǎn)生2.5Hz的方波(假設(shè)delay的時(shí)間是ms)
放開PA0后,PB1就會(huì)比較隨機(jī)的停在0V或3.3V

如果你想點(diǎn)動(dòng)PA0來(lái)控制PB1
大約可以這樣改(沒用過(guò)AVR,看了一下手冊(cè)):
  1. int main(void)
  2. {
  3.         unsigned char temp=0;
  4.         DDRB = 0x0F;//輸入輸出設(shè)定只要設(shè)一次
  5.         while(1)
  6.         {
  7.                 temp = (PINA & (_BV(DDA0)));  //KEY
  8.                 if (!temp)
  9.                 {
  10.                         delay(200);
  11.                         if(!temp)
  12.                         {//方法1
  13.                                 if(PORTB & 0x02)
  14.                                 {
  15.                                         PORTB &= 0xFD;
  16.                                 }else{
  17.                                         PORTB |= 0x02;
  18.                                 }
  19.                                 //方法2
  20.                                 //PORTB ^= 0x02;//異或
  21.                         }
  22.                 }
  23.         }
  24.         return 0;
  25. }
復(fù)制代碼





回復(fù)

使用道具 舉報(bào)

5#
ID:881204 發(fā)表于 2021-8-25 11:40 | 只看該作者
本帖最后由 灰小伙 于 2021-8-25 15:52 編輯
lkc8210 發(fā)表于 2021-8-25 09:56
不明白你的代碼為什么要這樣寫
根據(jù)你的代碼,當(dāng)按下PA0時(shí)
PB1會(huì)產(chǎn)生2.5Hz的方波(假設(shè)delay的時(shí)間是ms)

謝謝大佬指點(diǎn),我的工作目的是:按一次KEY,PB1輸出高;再按一次KEY,PB1輸出低。并且一直這樣檢測(cè)是否有按鍵輸入,如果有的話,PB1的輸出就翻轉(zhuǎn),并保持到下一次按鍵輸入。
謝謝!
回復(fù)

使用道具 舉報(bào)

6#
ID:881204 發(fā)表于 2021-8-27 10:17 | 只看該作者
lkc8210 發(fā)表于 2021-8-25 09:56
不明白你的代碼為什么要這樣寫
根據(jù)你的代碼,當(dāng)按下PA0時(shí)
PB1會(huì)產(chǎn)生2.5Hz的方波(假設(shè)delay的時(shí)間是ms)

謝謝lkc8210大佬的指導(dǎo),我明白了為什么會(huì)產(chǎn)生方波。
只是目前按鍵的靈敏度還是不夠,10次有3-4次按下去沒反應(yīng),繼續(xù)努力中。
回復(fù)

使用道具 舉報(bào)

7#
ID:161164 發(fā)表于 2021-8-27 10:30 | 只看該作者
灰小伙 發(fā)表于 2021-8-27 10:17
謝謝lkc8210大佬的指導(dǎo),我明白了為什么會(huì)產(chǎn)生方波。
只是目前按鍵的靈敏度還是不夠,10次有3-4次按下去 ...

把delay(200);改短一點(diǎn)試試
回復(fù)

使用道具 舉報(bào)

8#
ID:881204 發(fā)表于 2021-8-27 10:41 | 只看該作者
lkc8210 發(fā)表于 2021-8-27 10:30
把delay(200);改短一點(diǎn)試試

下面是最新的代碼。
void delay (unsigned int ms);
int main(void)
{
        unsigned char temp=0;
        DDRB = 0x0F;
        PORTB = 0x00;//輸出低
        while(1)
        {
                temp = (PINA & (_BV(DDA0)));  //KEY按下 檢測(cè)
        if (!temp)
        {
                delay(20);
                        if(!(PINA & (_BV(DDA0))))
                        {
                        while(!(PINA & (_BV(DDA0))));//KEY釋放 檢測(cè)
                        delay(10);
                         DDRB = 0x0F;
                         PORTB = 0x02; //輸出高
                        }
        }
                                temp = (PINA & (_BV(DDA0)));  //_BV是左移一位。
                                if (!temp)
                                {
                                delay(20);
                                        if(!(PINA & (_BV(DDA0))))
                                        {
                                        while(!(PINA & (_BV(DDA0)))); //KEY釋放 檢測(cè)
                                        delay(10);
                                        DDRB = 0x0F;
                                        PORTB = 0x00;//輸出低
                                        }
                                }
        }
          return 0;
}

void delay (unsigned int ms)
        {
                unsigned int i,j;
                for(i=0;i<ms;i++)
                {
                        for(j=0;j<1000;j++);
                }
        }
回復(fù)

使用道具 舉報(bào)

9#
ID:161164 發(fā)表于 2021-8-27 11:10 | 只看該作者
灰小伙 發(fā)表于 2021-8-27 10:41
下面是最新的代碼。
void delay (unsigned int ms);
int main(void)

???
為什么還是要這樣寫?
雖然加了釋放檢測(cè)令PB1不會(huì)產(chǎn)生方波
但這種寫法讓PB1 的輸出結(jié)果取決于是上半部分代碼先掃到按鍵還是下半部分先掃到
太隨機(jī)了
回復(fù)

使用道具 舉報(bào)

10#
ID:881204 發(fā)表于 2021-8-27 11:34 | 只看該作者
lkc8210 發(fā)表于 2021-8-27 11:10
???
為什么還是要這樣寫?
雖然加了釋放檢測(cè)令PB1不會(huì)產(chǎn)生方波

抱歉,可能是我的思路有問(wèn)題。
我想的是:為了“隨時(shí)檢測(cè)按鍵輸入值(因?yàn)橹灰_機(jī),用戶可能按無(wú)數(shù)次按鍵)”
回復(fù)

使用道具 舉報(bào)

11#
ID:881204 發(fā)表于 2021-8-30 09:58 | 只看該作者
換了個(gè)思路,情況有所改善,但還是有20%的按鍵不被認(rèn)識(shí)
代碼如下:
int main(void)
{
        unsigned char temp=0;
        unsigned char count = 0;
        unsigned char V6=0;
        DDRB = 0x0F;
        PORTB = 0x00;//初始化,輸出低
        while(1)
        {
                temp = (PINA & (_BV(DDA0)));  //KEY按下 檢測(cè)
                delay(10);
             while(!(PINA & (_BV(DDA0))));//KEY釋放 檢測(cè)
            delay(10);
                 switch(V6)
                 {
            case 0:
            if(temp==0)
            {
                    V6=1;
                    count++;
                    DDRB = 0x0F;
                    PORTB = 0x02; //輸出高
            }
            else
            {
                    V6=0;
                    count=0;
                    DDRB = 0x0F;
                    PORTB = 0x00; //輸出保持低
            }
            break;
        case 1:
                        if(temp==0)
                        {
                              V6=0;
                               count++;
                               DDRB = 0x0F;
                                PORTB = 0x00; //輸出低
                        }
                        else
                        {
                                V6=1;
                                count=0;
                                DDRB = 0x0F;
                                PORTB = 0x02; //輸出保持高
                        }
                        break;                       
                                        }
                                }
          return 0;
}
回復(fù)

使用道具 舉報(bào)

12#
ID:161164 發(fā)表于 2021-8-30 11:45 | 只看該作者
灰小伙 發(fā)表于 2021-8-30 09:58
換了個(gè)思路,情況有所改善,但還是有20%的按鍵不被認(rèn)識(shí)
代碼如下:
int main(void)

直接取反不香嗎?
PORTB = PORTB ^ 0x02;
回復(fù)

使用道具 舉報(bào)

13#
ID:881204 發(fā)表于 2021-8-30 12:39 | 只看該作者
lkc8210 發(fā)表于 2021-8-30 11:45
直接取反不香嗎?
PORTB = PORTB ^ 0x02;

大佬,你好~
因?yàn)槲疫@個(gè)按鍵要循環(huán)4個(gè)狀態(tài),按1次 輸出高。第2次 輸出方波1,第3次輸出方波2,第4次輸出低、
謝謝!
回復(fù)

使用道具 舉報(bào)

14#
ID:161164 發(fā)表于 2021-8-30 13:39 | 只看該作者
灰小伙 發(fā)表于 2021-8-30 12:39
大佬,你好~
因?yàn)槲疫@個(gè)按鍵要循環(huán)4個(gè)狀態(tài),按1次 輸出高。第2次 輸出方波1,第3次輸出方波2,第4次輸出 ...

方波1和方波2有什么分別?

另外,從你的代碼來(lái)看
PINB1 只會(huì)按1次 輸出高。第2次 輸出低,如此循環(huán)
回復(fù)

使用道具 舉報(bào)

15#
ID:881204 發(fā)表于 2021-8-30 14:05 | 只看該作者
lkc8210 發(fā)表于 2021-8-30 13:39
方波1和方波2有什么分別?

另外,從你的代碼來(lái)看

占空比不同。
回復(fù)

使用道具 舉報(bào)

16#
ID:881204 發(fā)表于 2021-8-30 14:06 | 只看該作者
lkc8210 發(fā)表于 2021-8-30 13:39
方波1和方波2有什么分別?

另外,從你的代碼來(lái)看

代碼沒加入。加了以后 程序執(zhí)行不了。。。
while(1)
        {
                temp = (PINA & (_BV(DDA0)));  //KEY按下 檢測(cè)
                delay(2);
             while(!(PINA & (_BV(DDA0))));//KEY釋放 檢測(cè)
            delay(2);
                 switch(V6)
                 {
            case 0:
            if((temp==0)&&(V6==0))
            {
                    V6=1;
                                DDRB = 0x0F;
                                PORTB = 0x01; //輸出高
            }
            else
            {
                    V6=0;
                                DDRB = 0x0F;
                                PORTB = 0x00; //輸出保持低
            }
            break;
////////////////////////////////////////////////////////////////////////                       
                        case 1:
                        if((temp==0)&&(V6==1))
                        {
                                V6=2;
                                while (1)//輸出方波
                                {
                                                                DDRB = 0x0F;
                                                                PORTB = 0x00; //輸出低
                                                                delay(10);
                                                                DDRB = 0x0F;
                                                                PORTB = 0x01; //輸出高
                                                                delay(10);       
                                                                if(temp==0)
                                                                break;
                                }
                        }
                        else
                        {
                                V6=1;
                                DDRB = 0x0F;
                                PORTB = 0x01; //輸出保持高
                        }
                        break;
                        ///////////////////////////////////////////////////////////////////////
                        case 2:
                        if((temp==0)&&(V6==2))
                        {
                    V6=0;
                                DDRB = 0x0F;
                                PORTB = 0x00; //輸出低
                        }
                        else
                        {
                                V6=1;
                                DDRB = 0x0F;
                                PORTB = 0x01; //輸出保持高
                        }
                        break;
                                                default:
                                                {
                                                        DDRB = 0x0F;
                                                        PORTB = 0x00; //輸出低
                                                }                       
                                        }                                 
                                }
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表