求助4×4键盘扫描简单程序,运行不起来。

[复制链接]
 楼主| soler_z 发表于 2009-9-2 22:11 | 显示全部楼层 |阅读模式

电路图,
想做个简单的键盘输入数字1-9,在LED上显示对应的值。
  1. //4×4键盘。P1口接7segLED,p3口接键盘,导入下面code无法显示,大家帮忙修改一下。谢谢了
  2. #include <REGX52.H>
  3. const unsigned char code seg7code[16] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d,
  4.                                                                                  0x7d, 0x07, 0x7f, 0x6f, 0x77,
  5.                                                                                  0x7c, 0x39, 0x5e, 0x79, 0x71};
  6. const unsigned char code KeyTable[16] = {0xee, 0xde, 0xbe, 0x7e,   //0,1,2,3
  7.                                                                                  0xed, 0xdd, 0xbd, 0x7d,   //4,5,6,7
  8.                                                                              0xeb, 0xdb, 0xbb, 0x7b,   //8,9,A,B
  9.                                                                                  0xe7, 0xd7, 0xb7, 0x77};  //C,D,E,F

  10. unsigned char keyscan(void);
  11. void delay(unsigned int);

  12. void main(void)
  13. {
  14.         unsigned char i;
  15.         unsigned char key;
  16.         P1 = 0;
  17.         while(1)
  18.         {
  19.                 key = keyscan();
  20.                 i = 0;
  21.                 while(key != KeyTable[i++]);//查表,找到对应的i,然后显示输出
  22.                 P1 = seg7code[--i];
  23.         }                       
  24. }

  25. unsigned char keyscan(void)        //行列反转扫描法
  26. {
  27.         unsigned char row_val, col_val;        //定义行,列
  28.         P3 = 0x0f;
  29.         col_val = P3 & 0x0f;
  30.         if(col_val != 0x0f)
  31.         {
  32.                 delay(100);
  33.                 if(col_val != 0x0f)
  34.                 {
  35.                         col_val = P3 & 0x0f;
  36.                         P3 = col_val | 0xf0;
  37.                         row_val = P3 & 0xf0;
  38.                         return (col_val | row_val);//组合行列键值。
  39.                 }
  40.         }
  41.         return 0xff;
  42. }

  43. void delay(unsigned int n)
  44. {
  45.         while(n--);
  46. }

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
FDLock 发表于 2009-9-2 23:53 | 显示全部楼层
>  key = keyscan();
>  i = 0;
>  while(key != KeyTable[i++]);//查表,找到对应的i,然后显示输出

keyscan扫描到没有按键时返回0xFF,而在整个KeyTable表中都没有0xFF,则上面的查表将会出错(甚至死循环)。
 楼主| soler_z 发表于 2009-9-3 00:52 | 显示全部楼层
谢谢,明白了,那我的代码可以继续写下去了。
 楼主| soler_z 发表于 2009-9-4 01:56 | 显示全部楼层
  1. #include <REGX52.H>

  2. #define KeybufSize 16 //键盘缓存大小

  3. unsigned char KeyBuf[KeybufSize]; //键盘缓存数组,先进先出
  4. unsigned char KeybufWp = 0;        //缓存写键值
  5. unsigned char KeybufRp = 0;        //缓存读键值

  6. unsigned char keyHit(void);        //函数判断是否有键按下
  7. unsigned char keyGet(void);         //函数取键值
  8. void keyPut(unsigned char ucKeyVal); //

  9. const unsigned char code seg7code[] ={0x3f, 0x06, 0x5b, 0x4f,
  10.                                         0x66, 0x6d,0x7d, 0x07,
  11.                                         0x7f, 0x6f, 0x77,0x7c,
  12.                                         0x39, 0x5e, 0x79, 0x71,0x00};  //seg7 com cathod
  13. unsigned char keyScan(void); //键盘扫描,行列反转法

  14. /*******************************************************************
  15. p1口接7段LED,p2接键盘输入,p2.0~2.3接KEYPAD-SMALLCALC的行a,b,c,d脚
  16. p2.4~2.7接4个列脚 ,单片机AT89C51,晶振频率12MHz
  17. ********************************************************************/
  18. void main(void)
  19. {
  20.    
  21.     TMOD = (TMOD & 0XF0) | 0X01; //定时器0,工作方式1
  22.     EA = 1;                                                 //开中断允许
  23.     ET0 = 1;
  24.     TH0 = (-20000)>>8;                         //定时器0计时20ms
  25.     TL0 = -20000;
  26.     TR0 = 1;
  27.     while(1)
  28.     {
  29.         if(keyHit() != 0)         //有键按下,输出显示。
  30.             P1 = seg7code[keyGet()];
  31.     }                        
  32. }

  33. /***********************************************************
  34. 利用T0内部中断来扫描键盘,20ms扫描一次,如有键按下,扫描键盘,
  35. 并存键盘缓存,如果按键松开,再判断有没有键按下。
  36. ************************************************************/
  37. void timer0intr(void) interrupt 1
  38. {
  39.     static unsigned char sts = 0;
  40.     TH0 = (-20000)>>8;
  41.     TL0 = -20000;
  42.         P2_0 = 1;         
  43.     switch(sts)
  44.     {
  45.         case 0: if(keyScan() != 0)   //判断有无键按下,有则转入状态1
  46.                     sts = 1;break;
  47.         case 1: if(keyScan() == 0)        //如果按错,转回状态0
  48.                     sts = 0;
  49.                 else
  50.                 {
  51.                     sts = 2;
  52.                     keyPut(keyScan());  //确认有键按下,转入状态2,并把键号写入缓存
  53.                 }
  54.                 break;
  55.         case 2: if(keyScan() == 0)
  56.                     sts = 3; break;         //判断按键松开,转入状态3
  57.         case 3: if(keyScan() != 0)
  58.                     sts = 2;
  59.                 else
  60.                     sts = 0;         //确认按键已经松开,会状态0,否则回状态2,重新判断
  61.                 break;
  62.     }  
  63. }

  64. /***********************************************************
  65.                                  行列反转键盘扫描
  66. ************************************************************/

  67. unsigned char keyScan( void ) //返回0表示无按键,或无效按键,其它值为按键编码值   
  68. {
  69.         code unsigned char keyCode[16]=   
  70.         //0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF   
  71.         { 0,   0,   0,   0,   0,   0,   0,   1,   0,   0,   0,   2,   0,   3,   4,   0 };   
  72.          unsigned char x, y, retVal;   
  73.          P1=0x0f;    //低四位输入,高四位输出0   
  74.          x=P1&0x0f;   //P1输入后,清高四位,作为X值   
  75.          P1=0xf0;    //高四位输入,低四位输出0   
  76.          y=(P1 >> 4) & 0x0f; //P1输入后移位到低四位,并清高四位,作为Y值   
  77.          retVal = keyCode[x]*4 + keyCode[y]; //根据本公式倒算按键编码   
  78.          if( retVal==0 ) return(0);
  79.         else return( retVal-4 );     
  80. }   

  81. unsigned char keyHit(void)  //判断是否有键按下。
  82. {
  83.      if(KeybufWp == KeybufRp)
  84.         return 0;
  85.     else return 1;
  86. }

  87. unsigned char keyGet(void)         //读取键值
  88. {
  89.     unsigned char retVal;//暂存读出键值
  90.     while(!keyHit());
  91.     retVal = KeyBuf[KeybufRp];
  92.     if(++KeybufRp >= KeybufSize)
  93.         KeybufRp = 0;
  94.     return retVal;
  95. }

  96. void keyPut(unsigned char ucKeyVal)
  97. {
  98.      KeyBuf[KeybufWp] = ucKeyVal;//键值存入数组
  99.     if(++KeybufWp >= KeybufSize)
  100.         KeybufWp = 0;
  101. }
哎,问题又来了,突然发现按下键盘之后显示的值完全不对,并且只能按一个键,
并且再也无法输入,不知道是哪的问题,大家帮忙看看吧。谢谢了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

13

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部