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

QQ登錄

只需一步,快速開始

帖子
查看: 1938|回復(fù): 28
打印 上一主題 下一主題
收起左側(cè)

請(qǐng)教51單片機(jī)矩陣鍵盤反轉(zhuǎn)法掃描遇到的無(wú)法解決的問(wèn)題

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:349276 發(fā)表于 2024-10-30 17:06 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
mcu 是stc8a8k64s4a12單片機(jī),矩陣鍵盤是帶上拉電阻的真實(shí)鍵盤,P1口連接,采用反轉(zhuǎn)法掃描。1.必須設(shè)置成開漏模式才能采集到數(shù)據(jù)。其它模式都不行,不知道啥原因。2.第一次置P1=0xf0,可以正確設(shè)置,且能正確采集回按鍵情況;第二次反轉(zhuǎn) 設(shè)置P1=0x0f,然后采集p1口的數(shù)據(jù)完全是錯(cuò)的,比如只采集p1一次,得到的數(shù)據(jù)是第一次(反轉(zhuǎn)設(shè)置之前)的數(shù)據(jù);比如重復(fù)寫一次采集數(shù)據(jù)(連續(xù)采集兩次),得到的數(shù)據(jù)跟采集一次的又完全不同,且還發(fā)現(xiàn)低電平被拉高了(本來(lái)應(yīng)該是高電平被拉低)。
沒招數(shù)了。請(qǐng)大神指點(diǎn)下迷津。

P1為KEY_ScanPort  要設(shè)置這個(gè) 初始化 P1M1=0xff;P1M0=0xff;才能讀回?cái)?shù)據(jù)

        
        KEY_ScanPort=0xF0;                 //列線為輸入,行線為輸出,并置行線輸出全為0
        temp=KEY_ScanPort;                 //讀P1口       能正確得到數(shù)據(jù)
        temp=temp&0xF0;
        temp=~((temp>>4)|0xF0);
        if(temp==1)
                key=0;
        else if(temp==2)
                key=1;
        else if(temp==4)
                key=2;
        else if(temp==8)
                key=3;
        KEY_ScanPort=0xFF;//for read  這一句可有可不有,但proteus里那鍵盤keypad仿真必須得有這個(gè),否則無(wú)法采集
        KEY_ScanPort=0x0F;                 //設(shè)置反轉(zhuǎn),行線為輸入,列線為輸出,并置列線輸出全為0
        MDelay(3);        //懷疑引腳電平反轉(zhuǎn)起效果時(shí)有一個(gè)較長(zhǎng)的時(shí)間延遲
        temp=KEY_ScanPort;                 //讀P1口 讀出來(lái)跟沒有反轉(zhuǎn)之前的采集情況一樣,就是高四位有3個(gè)1
        temp=KEY_ScanPort;                //重復(fù)采集一下發(fā)現(xiàn)低四位有4個(gè)1 高四位有1~2個(gè)1,低電平反而被拉高了。
       temp=KEY_ScanPort;                //再重復(fù)采集一下發(fā)現(xiàn)低四位有4個(gè)1,高四位是4個(gè)0,不動(dòng)了,按鍵沒效果。反正反轉(zhuǎn)后無(wú)法采集到正確信息
        temp=temp&0x0F;
        temp=~(temp|0xF0);        
        if(temp==1)
                key=key+0;
        else if(temp==2)
                key=key+4;
        else if(temp==4)
                key=key+8;
        else if(temp==8)
                key=key+12;
                             

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

使用道具 舉報(bào)

沙發(fā)
ID:1109793 發(fā)表于 2024-10-30 19:07 | 只看該作者
矩陣怎么接的?4*4的?一次拉低4個(gè)IO,怎么判斷是那個(gè)IO上的KEY?
回復(fù)

使用道具 舉報(bào)

板凳
ID:446156 發(fā)表于 2024-10-31 09:44 | 只看該作者
反轉(zhuǎn)法矩陣掃描當(dāng)然要配置成開漏模式啦必須所有用到的IO都是開漏才行,這樣你讓IO輸出高電平的時(shí)候該IO可以被外界信號(hào)拉低或者拉高方便你檢測(cè),這和IIC的SDA要配置成開漏一個(gè)原理。我沒看明白你是開漏模式下完全正常還是開漏模式下也存在問(wèn)題。還有設(shè)置完IO口狀態(tài)再去讀取IO口電平時(shí)中間要間隔一段時(shí)間一般情況下1ms完全夠了,因?yàn)殡娐反嬖诩纳娙�,開漏模式下IO狀態(tài)從低到高需要上拉電阻給寄生電容充電需要時(shí)間不會(huì)瞬間變化的。
回復(fù)

使用道具 舉報(bào)

地板
ID:446156 發(fā)表于 2024-10-31 09:46 | 只看該作者
xiaobendan001 發(fā)表于 2024-10-30 19:07
矩陣怎么接的?4*4的?一次拉低4個(gè)IO,怎么判斷是那個(gè)IO上的KEY?

反轉(zhuǎn)法,先把四個(gè)列線拉低檢測(cè)4個(gè)行線電平,然后把4個(gè)行線拉低去檢測(cè)4個(gè)列線電平。把兩次檢測(cè)結(jié)果或在一起就能知道是哪個(gè)按鍵被按下了
回復(fù)

使用道具 舉報(bào)

5#
ID:619259 發(fā)表于 2024-10-31 10:25 | 只看該作者
矩陣鍵盤反轉(zhuǎn)法掃描實(shí)例,以 P1口為例。
1.拉低P1低4位;
2.若P1高4位出現(xiàn)低電平,則讀P1的值;
3.反轉(zhuǎn),釋放P1低4位,拉低P1高4位;
4.讀P1的值;
5.將步驟2和4的值或運(yùn)算;
6.對(duì)步驟5的值進(jìn)行判斷或查表,執(zhí)行給定任務(wù)。
回復(fù)

使用道具 舉報(bào)

6#
ID:1109793 發(fā)表于 2024-10-31 12:51 | 只看該作者
cy009 發(fā)表于 2024-10-31 10:25
矩陣鍵盤反轉(zhuǎn)法掃描實(shí)例,以 P1口為例。
1.拉低P1低4位;
2.若P1高4位出現(xiàn)低電平,則讀P1的值;

這樣就是需要都設(shè)置標(biāo)準(zhǔn)IO才行吧,設(shè)置開漏就是沒有上拉電阻,那么高電平由誰(shuí)提供?
我還真沒試過(guò)這種,都是一個(gè)IO一個(gè)IO的拉低,然后檢測(cè)另外四個(gè)的電平變化。
回復(fù)

使用道具 舉報(bào)

7#
ID:446156 發(fā)表于 2024-10-31 14:05 | 只看該作者
xiaobendan001 發(fā)表于 2024-10-31 12:51
這樣就是需要都設(shè)置標(biāo)準(zhǔn)IO才行吧,設(shè)置開漏就是沒有上拉電阻,那么高電平由誰(shuí)提供?
我還真沒試過(guò)這種, ...

外部上拉電阻提供高電平啊,所有的按鍵電路無(wú)論矩陣也好獨(dú)立按鍵也好不都得配上拉電阻嗎?
回復(fù)

使用道具 舉報(bào)

8#
ID:161164 發(fā)表于 2024-10-31 14:57 | 只看該作者
上拉電阻阻值多大?
回復(fù)

使用道具 舉報(bào)

9#
ID:349276 發(fā)表于 2024-10-31 15:44 | 只看該作者
xiaobendan001 發(fā)表于 2024-10-30 19:07
矩陣怎么接的?4*4的?一次拉低4個(gè)IO,怎么判斷是那個(gè)IO上的KEY?

4*4的,p1低四位接行,高四位接列。每條線都有上拉電阻,上拉電阻電路是放矩陣鍵盤里面的。反轉(zhuǎn)法是f0   再0f的,按鍵按下,只會(huì)有一個(gè)高電平會(huì)被拉低的。原理上來(lái)說(shuō)。仿真都沒有問(wèn)題的。就是實(shí)際這個(gè)鍵盤,反轉(zhuǎn)后采集不回來(lái)數(shù)據(jù)。
回復(fù)

使用道具 舉報(bào)

10#
ID:349276 發(fā)表于 2024-10-31 15:45 | 只看該作者
qinlu123 發(fā)表于 2024-10-31 09:46
反轉(zhuǎn)法,先把四個(gè)列線拉低檢測(cè)4個(gè)行線電平,然后把4個(gè)行線拉低去檢測(cè)4個(gè)列線電平。把兩次檢測(cè)結(jié)果或在一 ...

就是行線拉低,采集不回?cái)?shù)據(jù)。
回復(fù)

使用道具 舉報(bào)

11#
ID:1133081 發(fā)表于 2024-10-31 15:45 | 只看該作者
給你一個(gè)4*4矩陣按鍵示例,端口設(shè)置為準(zhǔn)雙向模式。有無(wú)外置上拉電阻無(wú)所謂。程序放在主函數(shù)里查詢。key初值為0,鍵值輸出1~16,使用后可以清0.
void keyscan()                                        //按鍵掃描程序
{
        static bit sign=0;                        //按鍵狀態(tài)標(biāo)志
        static int count=0;                        //消抖計(jì)數(shù)變量                       
        unsigned char temp=0;                //臨時(shí)變量
        P1=0xf0;                                        //賦值P1 1111 0000
        if(P1!=0xf0)                                //檢測(cè)有按鍵按下
        {
                count++;                                //消抖計(jì)數(shù)
                if(count>=100 && sign==0)//根據(jù)主程序查詢周期調(diào)整count大小,約10~20ms防抖即可
                {                       
                        sign=1;                                //按鍵狀態(tài)標(biāo)志置1
                        temp=P1;                        //保存P1值xxxx 0000,x為0或1
                        temp|=0x0f;                        //保存temp按位或0x0f值xxxx 1111
                        P1=temp;                        //賦值P1 xxxx 1111
                        switch(P1)
                        {
                                case 0xee: key= 1; break;
                                case 0xde: key= 2; break;
                                case 0xbe: key= 3; break;
                                case 0x7e: key= 4; break;
                                case 0xed: key= 5; break;
                                case 0xdd: key= 6; break;
                                case 0xbd: key= 7; break;
                                case 0x7d: key= 8; break;
                                case 0xeb: key= 9; break;
                                case 0xdb: key=10; break;
                                case 0xbb: key=11; break;
                                case 0x7b: key=12; break;
                                case 0xe7: key=13; break;
                                case 0xd7: key=14; break;
                                case 0xb7: key=15; break;
                                case 0x77: key=16; break;
                        }
                }
        }
        else                                                //鍵抬起
        {
                sign=0;                                        //按鍵狀態(tài)標(biāo)志清0
                count=0;                                //消抖計(jì)數(shù)清0
        }
}
回復(fù)

使用道具 舉報(bào)

12#
ID:349276 發(fā)表于 2024-10-31 15:46 | 只看該作者
qinlu123 發(fā)表于 2024-10-31 09:44
反轉(zhuǎn)法矩陣掃描當(dāng)然要配置成開漏模式啦必須所有用到的IO都是開漏才行,這樣你讓IO輸出高電平的時(shí)候該IO可以 ...

我明天試試,延遲1ms后再采集試試。
回復(fù)

使用道具 舉報(bào)

13#
ID:349276 發(fā)表于 2024-10-31 15:50 | 只看該作者
cy009 發(fā)表于 2024-10-31 10:25
矩陣鍵盤反轉(zhuǎn)法掃描實(shí)例,以 P1口為例。
1.拉低P1低4位;
2.若P1高4位出現(xiàn)低電平,則讀P1的值;

您這步驟完全正確。就是第三步,代碼直接用  P1=0x0f,起不了作用。您所謂 釋放p1低四位,拉低p1高四位,是不是不使用的P1=0x0f語(yǔ)句?如不使,應(yīng)該怎么用?
回復(fù)

使用道具 舉報(bào)

14#
ID:349276 發(fā)表于 2024-10-31 15:51 | 只看該作者
xiaobendan001 發(fā)表于 2024-10-31 12:51
這樣就是需要都設(shè)置標(biāo)準(zhǔn)IO才行吧,設(shè)置開漏就是沒有上拉電阻,那么高電平由誰(shuí)提供?
我還真沒試過(guò)這種, ...

鍵盤上提供了上拉結(jié)構(gòu)的,高電平有鍵盤提供。開漏是可以的。
回復(fù)

使用道具 舉報(bào)

15#
ID:1109793 發(fā)表于 2024-10-31 16:39 | 只看該作者
qinlu123 發(fā)表于 2024-10-31 14:05
外部上拉電阻提供高電平啊,所有的按鍵電路無(wú)論矩陣也好獨(dú)立按鍵也好不都得配上拉電阻嗎?

既然要用外部上拉,為何還要關(guān)閉內(nèi)部上拉?還是說(shuō)這種接法和讀取方法需要非常精確的上拉,內(nèi)部因?yàn)橹圃旃に噯?wèn)題誤差太大不能用?那么多少才最好用?
回復(fù)

使用道具 舉報(bào)

16#
ID:349276 發(fā)表于 2024-10-31 23:25 來(lái)自觸屏版 | 只看該作者
WL0123 發(fā)表于 2024-10-31 15:45
給你一個(gè)4*4矩陣按鍵示例,端口設(shè)置為準(zhǔn)雙向模式。有無(wú)外置上拉電阻無(wú)所謂。程序放在主函數(shù)里查詢。key初值 ...

這代碼也許不錯(cuò),第二次只有一個(gè)低電平線。明天試試效果。
回復(fù)

使用道具 舉報(bào)

17#
ID:349276 發(fā)表于 2024-10-31 23:30 來(lái)自觸屏版 | 只看該作者
xiaobendan001 發(fā)表于 2024-10-31 16:39
既然要用外部上拉,為何還要關(guān)閉內(nèi)部上拉?還是說(shuō)這種接法和讀取方法需要非常精確的上拉,內(nèi)部因?yàn)橹圃旃?...

是這樣的,設(shè)置為其它模式,一次數(shù)據(jù)都讀不回來(lái)。設(shè)置為開漏,立刻就讀回來(lái)了。原因我不會(huì)分析。另外查到stm32,如果是開漏模式,還有幾個(gè)寄存器要聯(lián)合配置,比如有個(gè)配置低電平究竟是哪個(gè)范圍,范圍不對(duì)采集的數(shù)據(jù)可能會(huì)錯(cuò)。不知道是不是因?yàn)闆]配置的原因?我不知道stc8有沒有這些寄存器。沒看它的說(shuō)明書。
回復(fù)

使用道具 舉報(bào)

18#
ID:579397 發(fā)表于 2024-11-1 00:48 | 只看該作者
        KEY_ScanPort=0xF0;
******
        KEY_ScanPort=0xFF;//for read  這一句可有可不有,但proteus里那鍵盤keypad仿真必須得有這個(gè),否則無(wú)法采集

這里加一個(gè)延時(shí)試試,我解釋不了,但我這樣做就正常了
        KEY_ScanPort=0x0F;                 //設(shè)置反轉(zhuǎn),行線為輸入,列線為輸出,并置列線輸出全為0
回復(fù)

使用道具 舉報(bào)

19#
ID:446156 發(fā)表于 2024-11-1 08:12 | 只看該作者
xiaobendan001 發(fā)表于 2024-10-31 16:39
既然要用外部上拉,為何還要關(guān)閉內(nèi)部上拉?還是說(shuō)這種接法和讀取方法需要非常精確的上拉,內(nèi)部因?yàn)橹圃旃?...

習(xí)慣問(wèn)題吧,我很少用單片機(jī)的內(nèi)部上拉,51多年不用了不了解,stm32的內(nèi)部上拉電阻太大很多場(chǎng)合都不合適�?戳讼�51IO設(shè)置結(jié)合我之前做51時(shí)候的經(jīng)歷把IO配置成準(zhǔn)雙向IO也行即M1=0;M0=0
回復(fù)

使用道具 舉報(bào)

20#
ID:446156 發(fā)表于 2024-11-1 08:15 | 只看該作者
萬(wàn)家燈火51 發(fā)表于 2024-10-31 15:45
就是行線拉低,采集不回?cái)?shù)據(jù)。

你先檢查IO輸入檢測(cè)有沒有問(wèn)題,把8和IO都輸出0讀一下IO狀態(tài)然后都輸出1再讀一下狀態(tài)。用萬(wàn)用表量一量是不是對(duì)
回復(fù)

使用道具 舉報(bào)

21#
ID:192020 發(fā)表于 2024-11-1 14:21 | 只看該作者
temp=KEY_ScanPort;                 //讀P1口 讀出來(lái)跟沒有反轉(zhuǎn)之前的采集情況一樣,就是高四位有3個(gè)1
不知道你是用什么方法來(lái)讀temp值的?這時(shí)候萬(wàn)用表量一下高低電平是不是和讀的符合,感覺大概率硬件問(wèn)題
回復(fù)

使用道具 舉報(bào)

22#
ID:349276 發(fā)表于 2024-11-1 18:47 來(lái)自觸屏版 | 只看該作者
問(wèn)題解決��!首先非常感謝各位大佬積極出主意和提供經(jīng)驗(yàn)�?吹侥鷤兊幕貜�(fù),一下子覺得很踏實(shí)。困惑幾周的問(wèn)題,綜合大家的想法突然有了思路。問(wèn)題出在兩個(gè)地方:一個(gè)是沒有等待按鍵釋放就退出掃描,代碼又重復(fù)進(jìn)入掃描覆蓋了前一次的數(shù)據(jù)。這個(gè)是看到上面大佬代碼里搞那么多狀態(tài)標(biāo)記驚醒了我。第二個(gè)問(wèn)題是,開漏輸出,電平上拉全靠外電路,電阻值大小和是否有旁路電容等,這個(gè)拉高過(guò)程有點(diǎn)長(zhǎng)。電路理論里的三要素法,大致可以判斷,時(shí)間常數(shù)在毫秒級(jí)。線反轉(zhuǎn)法第一次設(shè)置后,要延時(shí)1毫秒,反轉(zhuǎn)后要延時(shí)2毫秒再采集數(shù)據(jù),就完全正確了。非常感謝大家之外,有幾點(diǎn)感觸。1是謝謝大家技術(shù)上的開放心態(tài)。。特別鄙視xxxx,看兩句話就要收錢要么就是各種坑各種牛皮。,知識(shí)都被鎖。2.是遇到問(wèn)題不要輕易懷疑芯片不可靠,是自己不可靠。3是這個(gè)論壇能查到真東西,能解決真問(wèn)題。到搜這個(gè)論壇很難搜到,全是冒充51黑的網(wǎng)站。網(wǎng)絡(luò)生態(tài)太惡心。。廣告了
回復(fù)

使用道具 舉報(bào)

23#
ID:1109793 發(fā)表于 2024-11-2 07:19 | 只看該作者
萬(wàn)家燈火51 發(fā)表于 2024-11-1 18:47
問(wèn)題解決��!首先非常感謝各位大佬積極出主意和提供經(jīng)驗(yàn)�?吹侥鷤兊幕貜�(fù),一下子覺得很踏實(shí)。困惑幾周的問(wèn) ...

不用開漏用標(biāo)準(zhǔn)IO不行嗎?要等2MS,這太浪費(fèi)時(shí)間了吧。2US還行
回復(fù)

使用道具 舉報(bào)

24#
ID:349276 發(fā)表于 2024-11-2 12:14 來(lái)自觸屏版 | 只看該作者
xiaobendan001 發(fā)表于 2024-11-2 07:19
不用開漏用標(biāo)準(zhǔn)IO不行嗎?要等2MS,這太浪費(fèi)時(shí)間了吧。2US還行

標(biāo)準(zhǔn)口,沒有用延時(shí)等待不行。改天測(cè)一下用了延時(shí),行不行。一般用鍵盤,按鍵都要延時(shí)5-10毫秒消抖的,正好掃描占用3毫秒,延時(shí)消抖3毫秒,效果很好。能滿足常規(guī)要求。
回復(fù)

使用道具 舉報(bào)

25#
ID:349276 發(fā)表于 2024-11-2 12:18 來(lái)自觸屏版 | 只看該作者
Graves 發(fā)表于 2024-11-1 14:21
temp=KEY_ScanPort;                 //讀P1口 讀出來(lái)跟沒有反轉(zhuǎn)之前的采集情況一樣,就是高四位有3個(gè)1
不 ...

查出來(lái)原因了。應(yīng)該是反復(fù)進(jìn)入掃描循環(huán),等待時(shí)間不夠,引腳反復(fù)處于高低電平變換造成的。
回復(fù)

使用道具 舉報(bào)

26#
ID:349276 發(fā)表于 2024-11-2 12:21 來(lái)自觸屏版 | 只看該作者
405616736 發(fā)表于 2024-11-1 00:48
KEY_ScanPort=0xF0;
******
        KEY_ScanPort=0xFF;//for read  這一句可有可不有,但prote ...

你提醒了我。應(yīng)該就是延時(shí)等待電平穩(wěn)定。這一句與讀準(zhǔn)備沒關(guān)系。就是起了延時(shí)作用。
回復(fù)

使用道具 舉報(bào)

27#
ID:1132991 發(fā)表于 2024-11-2 13:33 | 只看該作者
萬(wàn)家燈火51 發(fā)表于 2024-11-1 18:47
問(wèn)題解決��!首先非常感謝各位大佬積極出主意和提供經(jīng)驗(yàn)�?吹侥鷤兊幕貜�(fù),一下子覺得很踏實(shí)。困惑幾周的問(wèn) ...

當(dāng)時(shí)是搜A2開發(fā)板仿真電路才搜到的這個(gè)論壇
回復(fù)

使用道具 舉報(bào)

28#
ID:349276 發(fā)表于 2024-11-2 23:05 | 只看該作者
hxy52zero 發(fā)表于 2024-11-2 13:33
當(dāng)時(shí)是搜A2開發(fā)板仿真電路才搜到的這個(gè)論壇

用百度白天搜 51黑電子論壇  就能搜到,晚上用這個(gè)關(guān)鍵詞搜,會(huì)出來(lái)一堆顏色相關(guān)的,且翻幾頁(yè)都找不到這個(gè)論壇。我并且截圖留證了。百度惡心得很,想搜時(shí)又搜不到。
回復(fù)

使用道具 舉報(bào)

29#
ID:446156 發(fā)表于 2024-11-4 08:04 | 只看該作者
xiaobendan001 發(fā)表于 2024-11-2 07:19
不用開漏用標(biāo)準(zhǔn)IO不行嗎?要等2MS,這太浪費(fèi)時(shí)間了吧。2US還行

用我的驅(qū)動(dòng)就不用擔(dān)心浪費(fèi)時(shí)間,建議樓主如果做項(xiàng)目的話還是用我的驅(qū)動(dòng)吧,平常玩玩就無(wú)所謂了。還有樓主借鑒的程序也不咋地找個(gè)好點(diǎn)的用。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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