亚洲春色中文字幕久久久-三上亚,91精品国产亚一区二区三区,久久久九色综合亚洲成色777,涩涩视频下载,国产午夜亚洲精品午夜鲁丝片,国产精品A一区二区三区腾讯导航,影音先锋色情AV在线看片,蜜臀国产在线视频,极品少妇高潮啪啪无码吴梦梦 ,精品人妻无码一区二区三区手机版

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

4X4鍵盤不能按意圖顯示

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:409878 發(fā)表于 2025-8-14 22:27 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
最近在學(xué)習(xí)《例說51單片機》第三版,在第五章中學(xué)習(xí)4X4鍵盤的用法,程序就是按書上的程序來的,都沒法顯示。稍微調(diào)整了下,就只能顯示0,4,8,C。本來是要顯示0-E的,可其余的都顯示不出來。代碼和電路圖如下,麻煩各位幫我看看程序哪里有問題,非常感謝。
#include <reg51.h>
#define SEG7P P0
#define KEYP P2
#define u8 unsigned char

u8 code TAB[] = { 0xc0, 0xf9, 0xa4, 0xb0, 0x99,
                  0x92, 0x82, 0xf8, 0x80, 0x98,
                  0xa0, 0x83, 0xa7, 0xa1, 0x84,
                  0x8e, 0xbf, 0x7f
                };
u8 disp = 0x7f;

u8 scan[] = { 0xef, 0xdf, 0xbf, 0x7f};

void debouncer( void )
{
    u8 i;
    for( i = 2000; i > 0; i -- );
}

void delay1ms( u8 x )
{
    u8 i, k;
    for( i = x; i > 0; i -- )
        for( k = 128; k > 0; k -- );
}

void scanner( void )
{
    u8 col, row;
    u8 rowkey, kcode;
    for( col = 0; col < 4 ; col ++ )
    {
        KEYP = scan[col];

        SEG7P = disp;
        if( KEYP != scan[ col ] )
        {
            debouncer( );
            if( KEYP != scan[ col ] )
            {
                //debouncer( );
                rowkey = ((~KEYP) & 0x0f);
                if( 0x01 == rowkey )
                    row = 0;
                else if( 0x02 == rowkey )
                    row = 1;
                else if( 0x04 == rowkey )
                    row = 2;
                else if( 0x08 == rowkey )
                    row = 3;
                kcode = (4* col + row);
                disp = TAB[ kcode ];
                SEG7P = disp;
            }
        }
    }
    delay1ms(4);
}

void main( void )
{
    while( 1 )
    {
        scanner( );
    }
}


捕獲51.JPG (111.02 KB, 下載次數(shù): 0)

捕獲51.JPG

捕獲510.JPG (112.13 KB, 下載次數(shù): 0)

捕獲510.JPG

捕獲514.JPG (111.23 KB, 下載次數(shù): 0)

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

使用道具 舉報

沙發(fā)
ID:384109 發(fā)表于 2025-8-15 08:53 | 只看該作者
去掉上拉電阻試試
回復(fù)

使用道具 舉報

板凳
ID:1064915 發(fā)表于 2025-8-15 09:18 | 只看該作者
(1) 單獨測試數(shù)碼管

// 測試數(shù)碼管是否能顯示0-F
void test_display() {
    u8 i;
    for (i = 0; i < 16; i++) {
        SEG7P = TAB[i];
        delay1ms(500);
    }
}
如果數(shù)碼管能正常顯示0-F,說明問題在鍵盤掃描部分。

(2) 串口調(diào)試鍵值

// 通過串口打印鍵值(需初始化UART)
void send_keycode(u8 kcode) {
    SBUF = kcode + '0';  // 發(fā)送ASCII碼
    while (!TI);
    TI = 0;
}
這樣可以確認鍵盤掃描是否正確檢測到所有按鍵。
回復(fù)

使用道具 舉報

地板
ID:1133081 發(fā)表于 2025-8-15 09:54 | 只看該作者
你這寫法不但不易理解,更容易發(fā)生邏輯錯誤。改如下寫法易懂。


  1. #include <reg51.h>
  2. #define SEG7P P0
  3. #define KEYP P2
  4. #define u8 unsigned char

  5. u8 code TAB[] = { 0xc0, 0xf9, 0xa4, 0xb0, 0x99,
  6.                   0x92, 0x82, 0xf8, 0x80, 0x98,
  7.                   0xa0, 0x83, 0xa7, 0xa1, 0x84,
  8.                   0x8e, 0xbf, 0x7f, 0xbf
  9.                 };
  10. u8 kcode=16;
  11. void delay1ms( u8 x )
  12. {
  13.     u8 i, k;
  14.     for( i = x; i > 0; i -- )
  15.         for( k = 128; k > 0; k -- );
  16. }

  17. void scanner( void )
  18. {
  19.         static bit sign=0;                        //位變量
  20.         static u8 count=0;//計數(shù)變量

  21.         KEYP=0xf0;                                        //賦值P2 1111 0000
  22.         if(KEYP!=0xf0)                                //檢測有按鍵按下
  23.         {
  24.                 if(++count>=20 && sign==0)//
  25.                 {                       
  26.                         sign=1;                        //按鍵自鎖標志置1
  27.                         switch(KEYP)
  28.                         {
  29.                                 case(0Xe0):kcode = 0;break;
  30.                                 case(0Xd0):kcode = 1;break;
  31.                                 case(0Xb0):kcode = 2;break;
  32.                                 case(0X70):kcode = 3;break;
  33.                         }
  34.                         KEYP=0x0f;                        //賦值P2 0000 1111
  35.                         switch(KEYP)
  36.                         {
  37.                                 case(0X0e):kcode+= 0;break;
  38.                                 case(0X0d):kcode+= 4;break;
  39.                                 case(0X0b):kcode+= 8;break;
  40.                                 case(0X07):kcode+=12;break;
  41.                         }
  42.                 }
  43.         }
  44.         else                                                //鍵抬起
  45.         {
  46.                 sign=0;                                //按鍵自鎖標志清0
  47.                 count=0;                                //消抖計數(shù)清0
  48.         }
  49.         SEG7P = TAB[kcode];
  50.         delay1ms(1);
  51. }

  52. void main( void )
  53. {
  54.     while( 1 )
  55.     {
  56.         scanner( );
  57.     }
  58. }
復(fù)制代碼



回復(fù)

使用道具 舉報

5#
ID:341045 發(fā)表于 2025-8-15 09:56 | 只看該作者
void debouncer( void )
{
    u8 i;
    for( i = 2000; i > 0; i -- );
}

u8 i; i最大只能到255,不可能=2000,應(yīng)該是i = 200;
回復(fù)

使用道具 舉報

6#
ID:1004920 發(fā)表于 2025-8-15 10:18 | 只看該作者
學(xué)習(xí)單片機 以我做項目的經(jīng)驗。我個人建議學(xué)習(xí)I串口通訊,軟硬件IIC,SPI,PWM,單口按鍵等等的功能實現(xiàn),中斷也很重要。最不要學(xué)的就是矩陣鍵盤,這個根本用不上,真正要用到很多按鍵的時候有現(xiàn)成的芯片比如TM1668數(shù)碼管驅(qū)動和矩陣鍵盤。不會有IO口給你做矩陣。
回復(fù)

使用道具 舉報

7#
ID:1109793 發(fā)表于 2025-8-15 12:54 | 只看該作者
zch5200 發(fā)表于 2025-8-15 10:18
學(xué)習(xí)單片機 以我做項目的經(jīng)驗。我個人建議學(xué)習(xí)I串口通訊,軟硬件IIC,SPI,PWM,單口按鍵等等的功能實現(xiàn), ...

有道理
回復(fù)

使用道具 舉報

8#
ID:1157301 發(fā)表于 2025-8-15 13:55 | 只看該作者
zch5200 發(fā)表于 2025-8-15 10:18
學(xué)習(xí)單片機 以我做項目的經(jīng)驗。我個人建議學(xué)習(xí)I串口通訊,軟硬件IIC,SPI,PWM,單口按鍵等等的功能實現(xiàn), ...

約5年前我還真有客戶要求用這種4x4的鍵盤。
回復(fù)

使用道具 舉報

9#
ID:409878 發(fā)表于 2025-8-15 16:42 | 只看該作者
WL0123 發(fā)表于 2025-8-15 09:54
你這寫法不但不易理解,更容易發(fā)生邏輯錯誤。改如下寫法易懂。

其他算法很多,就是想知道這個算法為啥不行。
感覺應(yīng)該是for循環(huán)里面列掃描那段,但是感覺也沒問題,就是很奇怪為啥只能識別這幾個。
回復(fù)

使用道具 舉報

10#
ID:409878 發(fā)表于 2025-8-15 16:43 | 只看該作者
joyb 發(fā)表于 2025-8-15 09:18
(1) 單獨測試數(shù)碼管

// 測試數(shù)碼管是否能顯示0-F

串口調(diào)試怎么調(diào)?還沒接觸到這部分內(nèi)容。
回復(fù)

使用道具 舉報

11#
ID:384109 發(fā)表于 2025-8-15 19:59 | 只看該作者
應(yīng)該是rowkey = ((~KEYP) & 0x0f);有問題,用一個變量保存KEYP,然后在運算試試
回復(fù)

使用道具 舉報

12#
ID:409878 發(fā)表于 2025-8-15 21:00 | 只看該作者
人中狼 發(fā)表于 2025-8-15 19:59
應(yīng)該是rowkey = ((~KEYP) & 0x0f);有問題,用一個變量保存KEYP,然后在運算試試

沒用,看來不對。
回復(fù)

使用道具 舉報

13#
ID:1157301 發(fā)表于 2025-8-15 21:23 | 只看該作者
試試看

#include <reg51.h>
#define SEG7P P0
#define KEYP   P2
#define u8 unsigned char

u8 code TAB[] = {
    0xc0, 0xf9, 0xa4, 0xb0, 0x99,
    0x92, 0x82, 0xf8, 0x80, 0x98,
    0xa0, 0x83, 0xa7, 0xa1, 0x84,
    0x8e, 0xbf, 0x7f
};
u8 disp = 0x7f;

// 高 4 位掃描碼,低 4 位全為 1(輸入高阻)
u8 scan[] = { 0xE0 | 0x0F, 0xD0 | 0x0F, 0xB0 | 0x0F, 0x70 | 0x0F };

void debouncer(void)
{
    u8 i;
    for (i = 2000; i > 0; i--);
}

void delay1ms(u8 x)
{
    u8 i, k;
    for (i = x; i > 0; i--)
        for (k = 128; k > 0; k--);
}

void scanner(void)
{
    u8 col, row;
    u8 rowkey, kcode;

    for (col = 0; col < 4; col++)
    {
        // 輸出掃描信號,高 4 位決定列,低 4 位保持輸入(全 1)
        KEYP = scan[col];
        SEG7P = disp;

        // 讀取低 4 位(行)狀態(tài)
        rowkey = KEYP & 0x0F;

        if (rowkey != 0x0F) // 有按鍵被壓下
        {
            debouncer();
            rowkey = KEYP & 0x0F; // 再讀一次確認

            if (rowkey != 0x0F)
            {
                // 根據(jù)哪一位為 0 判斷行號
                if (rowkey == 0x0E) row = 0;
                else if (rowkey == 0x0D) row = 1;
                else if (rowkey == 0x0B) row = 2;
                else if (rowkey == 0x07) row = 3;

                kcode = (4 * col + row);
                disp = TAB[kcode];
                SEG7P = disp;
            }
        }
    }
    delay1ms(4);
}

void main(void)
{
    while (1)
    {
        scanner();
    }
}
回復(fù)

使用道具 舉報

14#
ID:1157301 發(fā)表于 2025-8-15 21:34 | 只看該作者
或試試比較簡單的改法

void scanner( void )
{
    u8 col, row;
    u8 rowkey, kcode;
    for( col = 0; col < 4 ; col ++ )
    {
        KEYP = scan[col]; // 輸出到 P2.0 ~ P2.3

        SEG7P = disp;
        if( KEYP != scan[ col ] )
        {
            debouncer( );
            if( KEYP != scan[ col ] )
            {
                rowkey = ((~KEYP) & 0xf0);
                if( 0x10 == rowkey )        
                    row = 0;
                else if( 0x20 == rowkey )   
                    row = 1;
                else if( 0x40 == rowkey )   
                    row = 2;
                else if( 0x80 == rowkey )   
                    row = 3;
                kcode = (4* col + row);
                disp = TAB[ kcode ];
                SEG7P = disp;
            }
        }
    }
    delay1ms(4);
}
回復(fù)

使用道具 舉報

15#
ID:161164 發(fā)表于 2025-8-15 22:00 | 只看該作者
如果試過明明代碼是正確的,別人可以成功仿真
但在你的電腦上就是怎么弄都不行
就代表Proteus有Bughttp://www.denmoz.com/bbs/dpj-236577-1.html

回復(fù)

使用道具 舉報

16#
ID:1133081 發(fā)表于 2025-8-16 07:30 | 只看該作者
suiwinder 發(fā)表于 2025-8-15 16:42
其他算法很多,就是想知道這個算法為啥不行。
感覺應(yīng)該是for循環(huán)里面列掃描那段,但是感覺也沒問題,就 ...

用樓主的程序不做任何修改在Proteus 8.9 仿真,沒有發(fā)現(xiàn)任何異常。加電顯示“.”,按矩陣鍵盤依次顯示0~F無誤。可能是14樓所言的Proteus版本有Bug。

回復(fù)

使用道具 舉報

17#
ID:409878 發(fā)表于 2025-8-16 09:44 | 只看該作者
WL0123 發(fā)表于 2025-8-16 07:30
用樓主的程序不做任何修改在Proteus 8.9 仿真,沒有發(fā)現(xiàn)任何異常。加電顯示“.”,按矩陣鍵盤依次顯示0~F ...

包含的那個補丁?也用的8.17 sP5版本的.
回復(fù)

使用道具 舉報

18#
ID:409878 發(fā)表于 2025-8-16 09:47 | 只看該作者
skilldog 發(fā)表于 2025-8-15 21:34
或試試比較簡單的改法

void scanner( void )

明天看看這個辦法ok不
回復(fù)

使用道具 舉報

19#
ID:420635 發(fā)表于 2025-8-16 10:32 來自觸屏版 | 只看該作者
從你提供的代碼和現(xiàn)象(僅顯示0、4、8、C)來看,問題核心在于行檢測邏輯與鍵盤硬件接線的匹配錯誤,導(dǎo)致只能識別第0行的4個按鍵(對應(yīng)0、4、8、C),其余行按鍵無法被檢測。
回復(fù)

使用道具 舉報

20#
ID:420635 發(fā)表于 2025-8-16 10:49 來自觸屏版 | 只看該作者
你的代碼中,rowkey是通過((~KEYP) & 0x0f)獲取的,這意味著你默認鍵盤的4行對應(yīng)P2口的低4位(P2.0~P2.3) ,但行判斷邏輯卻寫反了:   - 代碼中認為 rowkey=0x01(P2.0為低)對應(yīng)第0行,但實際硬件中,按下不同行的按鍵,rowkey的“1”所在位是從高位到低位排列(比如第0行對應(yīng)P2.3,rowkey=0x08;第3行對應(yīng)P2.0,rowkey=0x01)。  - 這就導(dǎo)致只有第0行(rowkey=0x08)的按鍵能被錯誤識別為row=0,其余行的rowkey(0x04、0x02、0x01)無法匹配任何row,最終只能顯示第0行的4個按鍵(0、4、8、C)。
回復(fù)

使用道具 舉報

21#
ID:409878 發(fā)表于 2025-8-17 23:05 | 只看該作者
房子 發(fā)表于 2025-8-16 10:49
你的代碼中,rowkey是通過((~KEYP) & 0x0f)獲取的,這意味著你默認鍵盤的4行對應(yīng)P2口的低4位(P2.0~P2.3)  ...

rowkey = 0x01是對應(yīng)的P2.0 = 1,rowkey = 0x08,是對應(yīng)P2.3 = 1的,硬件接法沒發(fā)現(xiàn)問題的。
回復(fù)

使用道具 舉報

22#
ID:409878 發(fā)表于 2025-8-17 23:15 | 只看該作者
skilldog 發(fā)表于 2025-8-15 21:34
或試試比較簡單的改法

void scanner( void )

這兩個代碼都試過了,不行。結(jié)果一樣。
回復(fù)

使用道具 舉報

23#
ID:409878 發(fā)表于 2025-8-17 23:16 | 只看該作者
WL0123 發(fā)表于 2025-8-16 07:30
用樓主的程序不做任何修改在Proteus 8.9 仿真,沒有發(fā)現(xiàn)任何異常。加電顯示“.”,按矩陣鍵盤依次顯示0~F ...

專門裝了8.9SP2,照樣不行。
回復(fù)

使用道具 舉報

24#
ID:1133081 發(fā)表于 2025-8-18 13:10 | 只看該作者
suiwinder 發(fā)表于 2025-8-17 23:16
專門裝了8.9SP2,照樣不行。

會不會是樓主編輯軟件做了深度優(yōu)化導(dǎo)致的。附件中是樓主發(fā)的原程序經(jīng)Keil uVision2編輯生成hex文件,導(dǎo)入Proteus 8 Professional仿真,運行正常。 矩陣鍵盤測試.rar (147.5 KB, 下載次數(shù): 0)

回復(fù)

使用道具 舉報

25#
ID:409878 發(fā)表于 2025-8-18 17:09 | 只看該作者
WL0123 發(fā)表于 2025-8-18 13:10
會不會是樓主編輯軟件做了深度優(yōu)化導(dǎo)致的。附件中是樓主發(fā)的原程序經(jīng)Keil uVision2編輯生成hex文件,導(dǎo)入 ...

用的是keil 5.38生成的hex文件。這個應(yīng)該不會有問題吧?
回復(fù)

使用道具 舉報

26#
ID:409878 發(fā)表于 2025-8-19 09:45 | 只看該作者
非常感謝各位的積極反饋,問題原因找到了。把鍵盤的4個上拉電阻取消之后,模擬就正常了。原程序沒問題。就是奇怪為啥10k的上拉電阻會造成無法正確識別按鍵。
回復(fù)

使用道具 舉報

27#
ID:314651 發(fā)表于 2025-8-26 09:36 | 只看該作者
矩陣按鍵是不要上拉電阻的,單片機的P0口反而需要做上拉。
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

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