欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3229|回復: 6
打印 上一主題 下一主題
收起左側

求助單片機矩陣按鍵的問題,已經調試了好多天了,謝謝

[復制鏈接]
跳轉到指定樓層
樓主
ID:320812 發表于 2018-5-2 21:48 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
我已經調試了好多天了,因為白天上班,晚上才有時間,但是連續4,5個晚上都發現不了原因,目前已經可以做到加法了,但是我只要一按鍵,比如按1,按一下馬上彈起,就會有N個1出現在8位數碼管上,出現多少根據按的時間決定,求好心人幫幫我。。我仿佛是知道因為程序記錄了我多次進行了按1的操作,可是我在按鍵檢測的時候用了if(keysta[j]==0),相當于按鍵彈起的時候才顯示1。我用的兩個74HC573接的8位數碼管,DUAN WEI兩個IO扣控制鎖存器的,拜謝了。。拜謝了。。

單片機源程序:
  1. #include<reg52.h>

  2. sbit L0=P1^0;                   //定義L0-L7小燈IO口
  3. sbit L1=P1^1;
  4. sbit L2=P1^2;
  5. sbit L3=P1^3;
  6. sbit L4=P1^4;
  7. sbit L5=P1^5;
  8. sbit L6=P1^6;
  9. sbit L7=P1^7;

  10. sbit o4=P3^0;                    //定義矩陣鍵盤IO口
  11. sbit o1=P3^1;
  12. sbit o2=P3^2;
  13. sbit o3=P3^3;
  14. sbit i1=P3^4;
  15. sbit i2=P3^5;
  16. sbit i3=P3^6;
  17. sbit i4=P3^7;

  18. sbit DUAN=P2^0;                                 //定義段選開關
  19. sbit WEI=P2^1;                                 //定義位選開關


  20. unsigned char ledbuff[8]={                       //數碼管顯示緩沖區
  21.     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  22. };

  23. unsigned char duanma[]={                                                           //定義單個數碼管段位,顯示0-F
  24.         0x3f,0x06,0x5b,0x4f,
  25.         0x66,0x6d,0x7d,0x07,
  26.         0x7f,0x6f,0x77,0x7c,
  27.         0x39,0x5e,0x79,0x71
  28.         };
  29. unsigned char weima[]={                                                                   //定義單個數碼管位,顯示第幾個數碼管
  30.         0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe
  31.         };        

  32. unsigned char keysta[4][4]={                                                 //定義矩陣按鍵的當前狀態
  33.         {1,1,1,1},
  34.         {1,1,1,1},
  35.         {1,1,1,1},
  36.         {1,1,1,1}
  37.         };
  38. unsigned char code keycodemap[4][4]={                                        //矩陣鍵盤標準鍵碼映射表
  39.         {0x31,0x32,0x33,0x26},                                                        //數字鍵1、數字鍵2、數字鍵3、加號
  40.         {0x34,0x35,0x36,0x25},                                                        //數字鍵4、數字鍵5、數字鍵6、減號
  41.         {0x37,0x38,0x39,0x28},                                                        //數字鍵7、數字鍵8、數字鍵9、乘號
  42.         {0x30,0x1b,0x0d,0x27}                                                        //數字鍵0、ESC鍵、  等號、   除號
  43. };

  44. void keydriver();

  45. unsigned char o=0;
  46. unsigned char cnt=0;

  47. void main()
  48. {

  49.         TMOD=0x01;          //計時器模式選擇為01,16位計時器
  50.         TH0=0xfc;          //為T0賦初值0xFC67,定時1ms
  51.         TL0=0x67;
  52.         TR0=1;                  //打開計時器
  53.         EA=1;                  //打開中斷總開關
  54.         ET0=1;                  //打開中斷T0
  55.         ledbuff[0]=duanma[0];

  56.         while(1)
  57.         {
  58.                 keydriver();                   //調用按鍵驅動函數
  59.         }
  60. }



  61. void shownumber(unsigned long num)                           /* 將一個無符號長整型的數字顯示到數碼管上,num-待顯示數字 */
  62. {

  63.         signed char i;
  64.         unsigned char buf[8];
  65.         for(i=0;i<8;i++)
  66.         {
  67.                 buf[i]=num%10;
  68.                 num=num/10;
  69.         }
  70.         L1=1;
  71.         for(i=7;i>=1;i--)                                                   //從最高位起,遇到0轉換為空格,遇到非0則退出循環
  72.         {
  73.                 if(buf[i]==0x00)
  74.                 {
  75.                         ledbuff[i]=0x00;
  76.                 }
  77.                 else
  78.                         break;
  79.         }
  80.         for(;i>=0;i--)                                                                 //剩余低位都如實轉換為數碼管顯示字符
  81.         {
  82.                 ledbuff[i]=duanma[buf[i]];
  83.         }
  84. }

  85. void keyaction(unsigned char keycode)
  86. {
  87.         static unsigned long result=0;                           //用于保存運算結果
  88.         static unsigned long addend=0;                           //用于保存輸入的加數
  89.         if((keycode>=0x30)&&(keycode<=0x39))                //輸入0-9的數字
  90.         {
  91.                 addend=(addend*10)+(keycode-0x30);           //整體十進制左移,新數字進入個位
  92.                 shownumber(addend);                                                //運算結果顯示到數碼管
  93.         }
  94.         else if(keycode==0x26)                   //按下加號
  95.         {
  96.                 result+=addend;
  97.                 addend=0;
  98.                 shownumber(result);
  99.         }
  100.         else if(keycode==0x0d)                        //按下等號
  101.         {
  102.                 result+=addend;
  103.                 addend=0;
  104.                 shownumber(result);
  105.         }
  106.         else if(keycode==0x1b)                         //按下ESC
  107.         {
  108.                 addend=0;
  109.                 result=0;
  110.                 shownumber(addend);
  111.         }
  112. }


  113. void keydriver()
  114. {
  115.         unsigned char i,j;
  116.         unsigned char backup[4][4]={                   //按鍵值備份,保存前一次的值
  117.         {1,1,1,1},
  118.         {1,1,1,1},
  119.         {1,1,1,1},
  120.         {1,1,1,1}
  121.         };
  122.         
  123.         for(i=0;i<4;i++)                                //循環檢測4*4的矩陣按鍵
  124.                 {
  125.                         for(j=0;j<4;j++)
  126.                         {
  127.                                 if(keysta[i][j]!=backup[i][j])                                //檢測按鍵動作
  128.                                 {                                                                                    //按鍵按下時執行動作
  129.                                         if(keysta[i][j]==0)
  130.                                         {
  131.                                                 keyaction(keycodemap[i][j]);               //調用按鍵動作函數
  132.                                         }
  133.                                 backup[i][j]=keysta[i][j];                                //刷新前一次的備份值
  134.                                 }

  135.                         }
  136.                 }
  137. }

  138. void keyscan()                                                                         //鍵盤消抖,檢測鍵盤是否按下
  139. {
  140.     static        unsigned char keyout=0;
  141.         unsigned char j;
  142.         static unsigned char keybuf[4][4]={
  143.         {0xff,0xff,0xff,0xff},
  144.         {0xff,0xff,0xff,0xff},
  145.         {0xff,0xff,0xff,0xff},
  146.         {0xff,0xff,0xff,0xff}
  147.         };
  148.         keybuf[keyout][0]=(keybuf[keyout][0]<<1)|i1;                        //消抖功能,對第一列鍵盤將keybuf[][]賦值為1111 1111或者0000 0000
  149.         keybuf[keyout][1]=(keybuf[keyout][1]<<1)|i2;
  150.         keybuf[keyout][2]=(keybuf[keyout][2]<<1)|i3;
  151.         keybuf[keyout][3]=(keybuf[keyout][3]<<1)|i4;

  152.         for(j=0;j<4;j++)
  153.         {
  154.                 if((keybuf[keyout][j])==0x00)                                //如果keybuf為0000 0000 則視為按下按鍵
  155.                 {
  156.                         keysta[keyout][j]=0;
  157.                 }
  158.                 else if((keybuf[keyout][j])==0xff)                         //如果keybuf為1111 1111 則視為彈起按鍵
  159.                 {
  160.                         keysta[keyout][j]=1;

  161.                 }
  162.         }



  163.         switch(keyout)                                                                         //對鍵盤進行行掃描
  164.         {
  165.                 case 0:o4=1;o1=0;break;
  166.                 case 1:o1=1;o2=0;break;
  167.                 case 2:o2=1;o3=0;break;
  168.                 case 3:o3=1;o4=0;break;
  169.                 default:break;
  170.         }

  171.          keyout++;
  172.          keyout=keyout&0x03;                                                                  //keyout到4清0


  173.                
  174. }

  175. void ledscan()                                                                                        //鍵盤顯示函數
  176. {

  177.     static unsigned char i = 0;  //動態掃描的索引
  178.         P0 = 0xFF;   //顯示消隱
  179.         switch(i)
  180.         {
  181.         case 0:
  182.                 WEI=1;P0=weima[0];WEI=0;DUAN=1;P0=ledbuff[0];i++;DUAN=0;break;                 //顯示個位
  183.         case 1:
  184.                 WEI=1;P0=weima[1];WEI=0;DUAN=1;P0=ledbuff[1];i++;DUAN=0;break;                 //顯示十位
  185.         case 2:
  186.                 WEI=1;P0=weima[2];WEI=0;DUAN=1;P0=ledbuff[2];i++;DUAN=0;break;                 //顯示百位
  187.         case 3:                        
  188.                 WEI=1;P0=weima[3];WEI=0;DUAN=1;P0=ledbuff[3];i++;DUAN=0;break;
  189.         case 4:                        
  190.                 WEI=1;P0=weima[4];WEI=0;DUAN=1;P0=ledbuff[4];i++;DUAN=0;break;
  191.         case 5:                        
  192.                 WEI=1;P0=weima[5];WEI=0;DUAN=1;P0=ledbuff[5];i++;DUAN=0;break;
  193.         case 6:                        
  194.                 WEI=1;P0=weima[6];WEI=0;DUAN=1;P0=ledbuff[6];i++;DUAN=0;break;
  195.         case 7:
  196.                 WEI=1;P0=weima[7];WEI=0;DUAN=1;P0=ledbuff[7];i++;DUAN=0;break;
  197.         default:i=0;break;
  198.         }
  199. }

  200. void interrupttimer0() interrupt 1                        //定時中斷檢測鍵盤,刷新數碼管
  201. {



  202.         TH0=0xfc;
  203.         TL0=0x67;
  204.         keyscan();   //調用按鍵掃描函數
  205.         ledscan();   //調用數碼管顯示掃描函數






  206. }
復制代碼
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:164602 發表于 2018-5-3 08:25 | 只看該作者
根據你所說的:可是我在按鍵檢測的時候用了if(keysta[j]==0),相當于按鍵彈起的時候才顯示1。

這個是沒有用的。
試想:在按鍵的抖動時,是不是會有很多次的等于零,而你的程序卻判斷有零就顯示,這與沒有消抖是一回事嘛。

所以,我的建議是:先消抖,就是延時啊,按下看時10ms左右,松開也延時10ms左右。要先消抖,穩定后才用你的判斷是否顯示。

這個應該是很基礎的了,你不會沒有例子吧?!
給你一個:
/*******************************************************************************
* 函 數 名         : KeyDown
* 函數功能                   : 檢測有按鍵按下并讀取鍵值
* 輸    入         : 無
* 輸    出         : 無
*******************************************************************************/
void KeyDown(void)
{
        char a=0;
        GPIO_KEY=0x0f;
        if(GPIO_KEY!=0x0f)//讀取按鍵是否按下
        {
                Delay10ms();//延時10ms進行消抖
                if(GPIO_KEY!=0x0f)//再次檢測鍵盤是否按下
                {
                       
                        //測試列
                        GPIO_KEY=0X0F;
                        switch(GPIO_KEY)
                        {
                                case(0X07):        KeyValue=0;break;
                                case(0X0b):        KeyValue=1;break;
                                case(0X0d): KeyValue=2;break;
                                case(0X0e):        KeyValue=3;break;
                        }
                        //測試行
                        GPIO_KEY=0XF0;
                        switch(GPIO_KEY)
                        {
                                case(0X70):        KeyValue=KeyValue;break;
                                case(0Xb0):        KeyValue=KeyValue+4;break;
                                case(0Xd0): KeyValue=KeyValue+8;break;
                                case(0Xe0):        KeyValue=KeyValue+12;break;
                        }
                        while((a<50)&&(GPIO_KEY!=0xf0))         //檢測按鍵松手檢測
                        {
                                Delay10ms();
                                a++;
                        }
                }
        }
}

這個例子程序,會返回按下鍵的值——從而可以判斷按下的是哪個鍵,你可以再根據返回的鍵值進行你程序需要的操作,比你的程序好多了,特別是消抖。
回復

使用道具 舉報

板凳
ID:213173 發表于 2018-5-3 09:12 | 只看該作者
樓主的按鍵掃描程序缺少自鎖語句,導致長按時重復響應,推薦一款精簡的4*4按鍵掃描程序和按鍵服務程序參考。
#define value 10                                //中斷周期1ms  消抖延時 10
unsigned char KeySec=0;                        //定義鍵值全局變量
/***********************************************************/
void keyscan()                                        //按鍵掃描程序(放在1ms中斷中)
{
        static bit sign=0;                        //按鍵自鎖標志
        static unsigned char count=0;//消抖計數變量                       
        unsigned char num=0;                //臨時變量
        P3=0xf0;                                        //賦值P3 1111 0000
        if(P3!=0xf0)                                //檢測有按鍵按下
        {
                count++;                                //消抖計數
                if((count>=value)&&(sign==0))
                {                       
                        sign=1;                                //按鍵自鎖標志置1,防止長按重復響應
                        num=P3;                                //保存P3值xxxx 0000,x為0或1
                        num|=0x0f;                        //保存num按位或0x0f值xxxx 1111
                        P3=num;                                //賦值P3 xxxx 1111
                        num=P3;                                //保存P3值xxxx xxxx
                        switch(num)
                        {
                                case 0xee: KeySec= 1; break;
                                case 0xde: KeySec= 2; break;
                                case 0xbe: KeySec= 3; break;
                                case 0x7e: KeySec= 4; break;
                                case 0xed: KeySec= 5; break;
                                case 0xdd: KeySec= 6; break;
                                case 0xbd: KeySec= 7; break;
                                case 0x7d: KeySec= 8; break;
                                case 0xeb: KeySec= 9; break;
                                case 0xdb: KeySec=10; break;
                                case 0xbb: KeySec=11; break;
                                case 0x7b: KeySec=12; break;
                                case 0xe7: KeySec=13; break;
                                case 0xd7: KeySec=14; break;
                                case 0xb7: KeySec=15; break;
                                case 0x77: KeySec=16; break;
                        }
                }
        }
        else                                                //按鍵抬起
        {
                sign=0;                                        //按鍵自鎖標志清0
                count=0;                                //消抖計數清0
        }
}
void key_service()                      //按鍵服務程序,放在主循環中
{
        switch(KeySec)
        {
                case 1:                                //事例1號鍵觸發
                //任務1
                KeySec=0;                          //鍵值清零,避免重復觸發
                break;                        //跳出當前程序

                case 2:                                //事例2號鍵觸發
                        //任務2
                KeySec=0;                          //鍵值清零,避免重復觸發
                break;                        //跳出當前程序
               
                //......
                //......

                case 16:                        //事例16號鍵觸發
                //任務16
                KeySec=0;                          //鍵值清零,避免重復觸發
                break;                         //跳出當前程序
        }                  
}
回復

使用道具 舉報

地板
ID:213173 發表于 2018-5-3 10:16 | 只看該作者
我用的兩個74HC573接的8位數碼管,DUAN WEI兩個IO扣控制鎖存器的
這是用兩個74HC573接的8位共陰數碼管動態顯示程序
void ledscan()//鍵盤顯示函數
{
        static unsigned char i=0;//靜態變量
        P0=0x00;                                //消隱
        DUAN=1;
        DUAN=0;
        P0=weima;                //位碼
        WEI=1;
        WEI=0;
        P0=ledbuff;                //段碼
        DUAN=1;
        DUAN=0;
        i++;
        if(i>=8)
                i=0;
}
回復

使用道具 舉報

5#
ID:126172 發表于 2018-5-3 12:00 | 只看該作者
彈起判斷應該放在按鍵執行后
回復

使用道具 舉報

6#
ID:320812 發表于 2018-5-3 22:14 | 只看該作者
謝謝各位大佬了,今天翹班研究這個程序,發現132.void keydriver()函數里面backup[4][4]沒有定義靜態,前面加個static一下就好了~唉~~~思維啊,思維啊~~板凳哥這個程序我仔細研究了下,確實比我的好多了~~拜謝
回復

使用道具 舉報

7#
ID:332416 發表于 2018-5-18 15:19 | 只看該作者
51單片機獨立按鍵
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit dula=P2^6;
sbit wela=P2^7;
sbit K1=P3^4;
sbit K2=P3^5;
sbit K3=P3^6;
sbit K4=P3^7;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uint aa;
uchar num1,num2,shi1,ge1,shi2,ge2;

void delay(uint z)
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}

void display(uchar num1,uchar num2)
{
        shi1=num1/10;
        ge1=num1%10;
        shi2=num2/10;
        ge2=num2%10;
       
        dula=1;
        P0=table[shi1];
        dula=0;
        P0=0xff;
        wela=1;
        P0=0xfe;
        wela=0;
        delay(1);

        dula=1;
        P0=table[ge1];
        dula=0;
        P0=0xff;
        wela=1;
        P0=0xfd;
        wela=0;
        delay(1);

        dula=1;
        P0=table[shi2];
        dula=0;
        P0=0xff;
        wela=1;
        P0=0xfb;
        wela=0;
        delay(1);

        dula=1;
        P0=table[ge2];
        dula=0;
        P0=0xff;
        wela=1;
        P0=0xf7;
        wela=0;
        delay(1);
}

void key()
{
        if(K1==0)
        {
                delay(5);
                if(K1==0)
                {
                        TR0=0;
                        while(!K1);
                }
        }

        if(K2==0)
        {
                delay(5);
                if(K2==0)
                {
                        if(num1==0)
                        {
                                num1=60;
                        }
                        num1--;
                        while(!K2);
                }
        }

        if(K3==0)
        {
                delay(5);
                if(K3==0)
                {
                        num1++;
                        if(num1>=60)
                        {
                                num1=num1-60;
                        }
                        while(!K3);
                }
        }

        if(K4==0)
        {
                delay(5);
                if(K4==0)
                {
                        TR0=1;
                        while(!K4);
                }
        }
}

void inint()
{
        TMOD=0x01;
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        EA=1;
        ET0=1;
        TR0=1;
}

void main()
{
        inint();
        while(1)
        {
                key();
                display(num1,num2);
        }
}

void zhongduan()interrupt 1
{
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        aa++;
        if(aa==20)
        {
                aa=0;
                num2++;
                if(num2==60)
                {
                        num2=0;
                        num1++;
                        if(num1==60)
                                num1=0;
                }
        }
}
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表