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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索

小玩意,3個普通IO識別22個按鍵試驗。有實物和程序

查看數(shù): 17684 | 評論數(shù): 34 | 收藏 25
關(guān)燈 | 提示:支持鍵盤翻頁<-左 右->
    組圖打開中,請稍候......
發(fā)布時間: 2013-7-9 23:08

正文摘要:

在51hei論壇吸取各位前輩的經(jīng)驗,將之前二極管用量多的問題優(yōu)化一下,目前不用二極管能接6鍵,2只二極管能接12鍵,6只二極管能接18鍵,9只二極管能接21鍵,第22鍵要單獨占用3只二極管最不化算。 實驗用89S51作試 ...

回復

ID:237471 發(fā)表于 2024-10-15 09:06
厲害呀,受教了
ID:163139 發(fā)表于 2024-10-14 20:29
由于還是新人 只有跟在高手后面慢慢做了!
ID:74252 發(fā)表于 2019-6-9 03:28
這是深夜逛論壇翻到寶了。!
ID:368541 發(fā)表于 2018-7-10 11:21
樓主辛苦  回復的很仔細
ID:297381 發(fā)表于 2018-3-26 17:17
6膜拜大佬
ID:89386 發(fā)表于 2015-10-14 19:48
超級贊! 新手 目前寫個 點亮一個LED都帶寫錯的。。。。直接膜拜!
ID:92052 發(fā)表于 2015-10-14 07:20
高手啊,掌握了精髓,所以可以隨心所欲了。
ID:91611 發(fā)表于 2015-10-5 11:18
這真是大神啊
ID:60246 發(fā)表于 2014-4-2 09:50
謝謝分享
ID:59341 發(fā)表于 2014-3-1 15:55
高手呀,收藏一下
ID:59151 發(fā)表于 2014-2-18 01:59
好東西,攬下試試,謝謝!
ID:58796 發(fā)表于 2014-2-14 00:00
學習。。。。。。。。。。。。。
ID:58267 發(fā)表于 2013-12-29 20:49
支持一下
ID:52286 發(fā)表于 2013-10-13 23:52
支持支持!!
ID:55734 發(fā)表于 2013-10-9 02:12
看看學習學習。。
ID:53315 發(fā)表于 2013-8-21 02:07
樓主,我沒看見按鍵?
ID:52177 發(fā)表于 2013-7-23 22:24
有套件賣嗎?我要
ID:51777 發(fā)表于 2013-7-13 20:32
由于還是新人 只有跟在高手后面慢慢做了!
ID:51654 發(fā)表于 2013-7-10 01:31
今天太晚了,下次再弄吧
ID:50574 發(fā)表于 2013-7-10 01:28

const unsigned char Key_tab[]=     //鍵碼映射表
{//  0  1  2  3  4  5  6  7  8  9   
        22, 0, 2, 0, 0, 0, 0, 0, 4, 0, //0
         0, 0, 0, 0, 0,18, 0, 0, 0, 0, //1X
         0, 0, 0, 0, 0, 0, 3,14, 0, 0, //2X
        20,10, 6, 0, 0, 0, 0, 0, 1,19, //3X
         0, 5, 0, 0, 0,15, 0,11, 0, 0, //4X
         0,17, 0, 0,13, 8, 0,21, 0, 9, //5X
        16,12, 7, 0                    //6X
};

//=============== 檢測按鍵 =================
void Key_scan()
{   
    unsigned char i;
    Key_count --;                        //掃描次序
    Key_count &= 3;
    switch (Key_count)                //按次序處理
    {
        case 2:                //第一輪掃描                                   
        if (PINA & 0x02) Key_state |= 0x01;    //讀入PINA.1,記錄于Key_state.0  
        if (PINA & 0x04) Key_state |= 0x02;    //讀入PINA.2,記錄于Key_state.1
                DDRA  &= ~(1<<0);  //A口位0先改為輸入  
        PORTA |=  (1<<0);  //A口位0上拉有效
                DDRA  &= ~(1<<2);  //A口位2先改為輸入  
        PORTA |=  (1<<2);  //A口位2上拉有效  
        PORTA &=  ~(1<<1);  //A口位1設(shè)定為0  
        DDRA  |=  (1<<1);  //A口位1改為輸出0         
        break;
     
        case 1:                                //每二輪掃描
        if (PINA & 0x01) Key_state |= 0x04;    //讀入PINA.0,記錄于Key_state.2  
        if (PINA & 0x04) Key_state |= 0x08;    //讀入PINA.2,記錄于Key_state.3
        PORTA |= (1<<1);
                DDRA &= ~(1<<1);
        PORTA &= ~(1<<2);
                DDRA  |= (1<<2);
                DDRA  &= ~(1<<0);   
        PORTA |=  (1<<0);  
        break;
     
        case 0:                                //每三輪掃描
        if (PINA & 0x02) Key_state |= 0x10;    //讀入PINA.1,記錄于Key_state.4  
        if (PINA & 0x01) Key_state |= 0x20;    //讀入PINA.0,記錄于Key_state.5
        PORTA |= (1<<2);
                DDRA &= ~(1<<2);
        PORTA &= ~(1<<0);
                DDRA  |= (1<<0);
                DDRA  &= ~(1<<1);   
        PORTA |=  (1<<1);  
        break;
     
        default:                        //每四輪掃描
        if (!(PINA&0X01)) Key_state &= ~(1<<0);
        if (!(PINA&0X02)) Key_state &= ~(1<<1);
        if (!(PINA&0X04)) Key_state &= ~(1<<2);
               
        break;
     }

        //======更新顯示緩沖區(qū)=======
        i = Key_tab[Key_state];                 
        if (i == 0)
        {
            Disp_buf[2] = 0x11;                //顯示三橫
            Disp_buf[1] = 0x11;
            Disp_buf[0] = 0x11;
        }
        else
        {
            Disp_buf[2] = 0x0c;     //字符"C"
            Disp_buf[1] = i / 10;   //鍵碼十位
            Disp_buf[0] = i % 10;      //鍵碼個位                        
        }
                //Key_state = 0;                        
}
Key_state什么時候清零才合適?要是4IO口的話,鍵碼又如何擴展呢?
ID:51654 發(fā)表于 2013-7-10 01:14
你沒細看程序,Key_state只用了6位,defalt那次的位用壓縮方或與前面6位中的3位相與。如果真的用到9位,鍵碼表占512字節(jié)就不好了。
至于dafalt后的break,在這里可用可不用,因為defalt后已經(jīng)是switch的未端。
你可以把文件傳到這里,或發(fā)至cowboy3@163.com
ID:50574 發(fā)表于 2013-7-10 01:11
四個IO掃3次,那Key_state就不止8位了,咋辦呢?
另外,default語句是不是漏了break?
樓主,能否把QQ號給我?我直接把仿真文件給你,就能直觀地看到錯誤了
ID:51654 發(fā)表于 2013-7-10 01:07
h333 發(fā)表于 2013-7-10 00:43
4個IO口,能掃多少鍵呢? ^_^

51的四個IO能掃65個鍵(或可以再多6個,但這6個可靠性不太好).
AVR的,2個IO就可以掃15鍵,4個IO可能超100了,你可以搜索一下h2feo4的貼子。
ID:51654 發(fā)表于 2013-7-10 01:06
先改變IO狀態(tài),立刻回讀IO,有時會出錯,IO外部受分布參數(shù)影響會有延時,特別是AVR上拉電阻較大,如果立該回讀可能出錯。
這里看似先讀再改變IO輸出,其實讀的時候,上一輪掃描中已經(jīng)把IO改變,到現(xiàn)在已過了5ms,IO狀態(tài)足夠穩(wěn)定了,這時讀入就可靠。
讀完了,再改變IO狀態(tài),其實是為下一次做好準備。

Key_state用組合生成,效果是一樣,只是處理繁瑣且占內(nèi)存也多。你先前的程序IO切換過程不正確才可能導致沒效果。
ID:50574 發(fā)表于 2013-7-10 00:43

4個IO口,能掃多少鍵呢? ^_^
ID:50574 發(fā)表于 2013-7-10 00:43
為什么 不是:
        case 2:                //第一輪掃描  
        DDRA  &= ~(1<<0);  //A口位0先改為輸入
        PORTA |=  (1<<0);  //A口位0上拉有效
        PORTA &=  ~(1<<1);  //A口位1設(shè)定為0
        DDRA  |=  (1<<1);  //A口位1改為輸出0                               //第一輪掃描  
        if (PINA & 0x02) Key_state |= 0x01;    //讀入PINA.1,記錄于Key_state.0
        if (PINA & 0x04) Key_state |= 0x02;    //讀入PINA.2,記錄于Key_state.1        
        break;  
       先改變IO口狀態(tài),再做鍵值判斷?
       我那個 Key_state = (KB5<<5 + KB4<<4 + KB3<<3 + KB2<<2 + KB1<<1 + KB0);效果也應該是一樣呀,只不過繁瑣了一些
ID:51654 發(fā)表于 2013-7-10 00:43
樓上還是沒搞明白,舉例說明一下

        case 2:                                //第一輪掃描
        if (PINA & 0x02) Key_state |= 0x01;    //讀入PINA.1,記錄于Key_state.0
        if (PINA & 0x04) Key_state |= 0x02;    //讀入PINA.2,記錄于Key_state.1
        DDRA  &= ~(1<<0);  //A口位0先改為輸入
        PORTA |=  (1<<0);  //A口位0上拉有效
        PORTA &=  (1<<1);  //A口位1設(shè)定為0
        DDRA  |=  (1<<1);  //A口位1改為輸出0
        break;             //以上端口變化順序不要更改,否則可以出現(xiàn)短路
ID:50574 發(fā)表于 2013-7-10 00:42

unsigned char KB0,KB1,KB2,KB3,KB4,KB5;


//=============== 檢測按鍵 =================
void Key_scan()
{   
    unsigned char i;
    Key_count --;                        //掃描次序
    Key_count &= 3;
    switch (Key_count)                //按次序處理
    {
        case 2:                                //第一輪掃描
        KB0 = PINA&0X02;  
        KB1 = PINA&0X04;  
        PORTA |= (1<<0);
                DDRA |= (1<<0);
        PORTA &= ~(1<<1);
                DDRA &= ~(1<<1);
        break;
     
        case 1:                                //每二輪掃描
        KB2 = PINA&0X04;
        KB3 = PINA&0X01;
        PORTA |= (1<<1);
                DDRA |= (1<<1);
        PORTA &= ~(1<<2);
                DDRA &= ~(1<<2);
        break;
     
        case 0:                                //每三輪掃描
        KB4 = PINA&0X01;
        KB5 = PINA&0X02;
        PORTA &= ~(1<<0);
                DDRA &= ~(1<<0);
        PORTA |= (1<<2);
                DDRA |= (1<<2);
        break;
     
        default:                        //每四輪掃描
        if (!(PINA&0X01)) KB0 = 0;
        if (!(PINA&0X02)) KB2 = 0;
        if (!(PINA&0X04)) KB4 = 0;
         

        //======更新顯示緩沖區(qū)=======
        Key_state = (KB0<<5 + KB1<<4 + KB2<<3 + KB3<<2 + KB4<<1 + KB5);
        i = Key_tab[Key_state];
        if (i == 0)
        {
            Disp_buf[2] = 0x11;                //顯示三橫
            Disp_buf[1] = 0x11;
            Disp_buf[0] = 0x11;
        }
        else
        {
            Disp_buf[2] = 0x0c;     //字符"C"
            Disp_buf[1] = i / 10;   //鍵碼十位
            Disp_buf[0] = i % 10;      //鍵碼個位
        }
        Key_state = 0;
    }
}     

void main()
{
   // TMOD = 0x10;            //定時器1,16位模式
    //TCON = 0xc0;            //TR1=1;TF1=1;
        init_devices();
    while(1)                //主循環(huán)
    {
        //Bus_drive();        //顯示總線驅(qū)動
        PORTB = LED_font[Disp_buf[2]];
        PORTC = LED_font[Disp_buf[1]];
        PORTD = LED_font[Disp_buf[0]];
        Key_scan();         //檢測按鍵
        delay_ms(5);        //延時5MS     
    }
}

怎么按,都是顯示C22
ID:51654 發(fā)表于 2013-7-10 00:24
h333 發(fā)表于 2013-7-10 00:21
樓主,兩點請求:
1、能否給我單總線數(shù)碼管顯示那塊的電路圖
2、我移植到AVR下,按鍵值不變,錯在哪里 ...

首先,AVR的IO不是準雙向口,在作為輸入時,需要開上拉電阻,當切換到輸出0時,需要改變PORTA和DDRA,你程序里沒有更改DDRA,因而不能動作。
其次,沒看到你對KB0~KB5的變量類型聲明,51中聲明為bit,AVR中的位操作比較麻煩,建議讀入時直接更新Key_state,取消KB0~KB5。
至于顯示的問題,我打算遲些開個新帖,因為和這主題關(guān)系不大。鍵碼已從 i= Key_tab[Key_state] 獲得,需要送顯示可自行處理。
ID:50574 發(fā)表于 2013-7-10 00:21

樓主,兩點請求:
1、能否給我單總線數(shù)碼管顯示那塊的電路圖
2、我移植到AVR下,按鍵值不變,錯在哪里呢?
   //=============== 檢測按鍵 =================
void Key_scan()
{   
    unsigned char i;
    Key_count --;                        //掃描次序
    Key_count &= 3;
    switch (Key_count)                //按次序處理
    {
        case 2:                                //第一輪掃描
        KB0 = PINA&0X02;  
        KB1 = PINA&0X04;  
        PORTA |= (1<<0);
        PORTA &= ~(1<<1);
        break;
     
        case 1:                                //每二輪掃描
        KB2 = PINA&0X04;
        KB3 = PINA&0X01;
        PORTA |= (1<<1);  
        PORTA &= ~(1<<2);
        break;
     
        case 0:                                //每三輪掃描
        KB4 = PINA&0X01;
        KB5 = PINA&0X02;
        PINA &= ~(1<<0);
        PORTA |= (1<<0);  
        break;
     
        default:                        //每四輪掃描
        if (!(PINA&0X01)) KB0 = 0;
        if (!(PINA&0X02)) KB2 = 0;
        if (!(PINA&0X04)) KB4 = 0;
         

        //======更新顯示緩沖區(qū)=======
        Key_state = KB0<<5 + KB1<<4 + KB2<<3 + KB3<<2 + KB4<<1 + KB5;
        i = Key_tab[Key_state];
        if (i == 0)
        {
            Disp_buf[2] = 0x11;                //顯示三橫
            Disp_buf[1] = 0x11;
            Disp_buf[0] = 0x11;
        }
        else
        {
            Disp_buf[2] = 0x0c;     //字符"C"
            Disp_buf[1] = i / 10;   //鍵碼十位
            Disp_buf[0] = i % 10;      //鍵碼個位
        }
        Key_state = 0;
    }
}

還有,你那個筆段代碼是BCD碼嗎?
ID:51654 發(fā)表于 2013-7-9 23:21
對于這種方式的按鍵識別方法,很多朋友擔心編程會很復雜,其實仔細分析后也很簡單.比如上面例子,其本的思路是依次把三個IO拉低,然后記錄另外兩個IO的狀態(tài),最后三個IO都不下拉,再記錄一次,就可得出的結(jié)果.對于按下不同的按鍵,就有不同的結(jié)果.如果只掃18鍵,那么最后一次掃描可以省掉,即掃描三次即可.實際應用時5MS的掃描間隔可以用定時中斷來實現(xiàn),這樣就只占用很少的MCU時間.
ID:51654 發(fā)表于 2013-7-9 23:15

作為試驗目的,沒有接按鍵,只焊了個鍵盤框架,用鑷子短路相應的節(jié)點來當按鍵。圖中接二極管陣列的三根線是3個IO,單獨的一根是地線。MCU發(fā)送串行數(shù)據(jù)給HC595驅(qū)動數(shù)碼管作鍵碼顯示。
ID:51654 發(fā)表于 2013-7-9 23:15
下次焊個四面體的4IO玩玩看

-----------------------------------------------------

二極管數(shù)量

6條楞,每楞兩個,12個

中間星型,4個

共16個

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

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

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 黄色网址免费在线观看 | 亚洲一区自拍 | 在线观看国产三级 | 天天爽夜夜骑 | 91av视频在线播放 | 国产亚洲一区二区三区 | 国产激情福利 | 精品久久久久久久久久久久 | 中文欧美日韩 | 龙珠z在线观看 | 91精品国产乱码麻豆白嫩 | 精品一区久久 | 国产精品中文字幕在线 | 欧美高清性xxxxhd | 中文字幕第一页在线 | a级在线免费观看 | 热久久久久| 成人在线视频一区二区三区 | 成人毛片在线视频 | 国产日韩欧美综合 | 国产精品久久久久影院色老大 | 丁香婷婷综合激情五月色 | 天天操综合网 | 成人久久18免费 | 国产精品一二区 | 国产精品1区2区 | 成人在线观看免费 | 国内精品久久精品 | 视频一区中文字幕 | 色婷婷久久久久swag精品 | 91在线成人 | 亚洲精品在线看 | 亚洲精品美女在线观看 | 天天干精品 | 成人av网页 | 97超碰在线免费 | 色www精品视频在线观看 | 免费小视频在线观看 | 日韩免费视频一区二区 | 爱爱小视频 | 国产高清一区二区三区 |