找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1068|回复: 6
打印 上一主题 下一主题
收起左侧

51单片机C语言程序位置的不对,导致的意外问题

[复制链接]
跳转到指定楼层
楼主
这是个矩阵按键,按下任意一个按键,数码管显示从0-F的值。
单片机C语言源程序如下:
  1. #include<reg52.h>

  2. sbit ADDR0 = P1^0;
  3. sbit ADDR1 = P1^1;
  4. sbit ADDR2 = P1^2;
  5. sbit ADDR3 = P1^3;
  6. sbit ENLED = P1^4;
  7. sbit KeyIn_1 = P2^7;
  8. sbit KeyIn_2 = P2^6;
  9. sbit KeyIn_3 = P2^5;
  10. sbit KeyIn_4 = P2^4;
  11. sbit KeyOut_1 = P2^3;
  12. sbit KeyOut_2 = P2^2;
  13. sbit KeyOut_3 = P2^1;
  14. sbit KeyOut_4 = P2^0;

  15. unsigned char code LedChar[16] = {                                         //数码管真值表
  16.     0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
  17.                 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
  18. };

  19. unsigned char keyStatus[4][4] = {                                          //全部矩阵按键当前的状态
  20.     {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
  21. };


  22. void main(){
  23.     unsigned char i,j;
  24.     unsigned char cnt = 0;
  25.     unsigned char backUp[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}}; //按键状态,保存前一次的值

  26.     EA = 1;
  27.     ENLED = 0;
  28.     ADDR3 = 1;
  29.     ADDR2 = 0;
  30.     ADDR1 = 0;
  31.     ADDR0 = 0;
  32.     TMOD = 0x01;
  33.     TH0 = 0xFC;
  34.     TL0 = 0x67;
  35.     ET0 = 1;
  36.     TR0 = 1;
  37.         P0 = LedChar[cnt];
  38.                         
  39.     while(1){
  40.         for(i = 0; i < 4; i++){
  41.             for(j = 0;j < 4; j++){
  42.                 if(backUp[i][j] != keyStatus[i][j]){
  43.                     if(backUp[i][j] == 0){ //按键抬起
  44.                     cnt++;
  45.                     if(cnt >= 16){
  46.                         cnt = 0;
  47.                     }
  48.                     P0 = LedChar[cnt];
  49.                     }
  50.                     backUp[i][j] = keyStatus[i][j];
  51.                 }
  52.             }
  53.                 }   
  54.         }
  55. }
  56. /*T0中断服务函数,判断按键状态并消抖*/
  57. void interruptTimer0() interrupt 1{
  58.     unsigned char i;
  59.     static unsigned char keyOut = 0;
  60.     static unsigned char keyBuff[4][4] = {
  61.         {0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF}          //矩阵按键扫描缓冲区
  62.     };  

  63.     TH0 = 0xFC;
  64.     TL0 = 0x67;
  65.     keyBuff[keyOut][0] = (keyBuff[keyOut][0] << 1) | KeyIn_1;  //按位与,将KeyIn_1的最后一位移入缓冲区。按位与的结果:最后1位是0就移入0,是1就移入1。
  66.     keyBuff[keyOut][1] = (keyBuff[keyOut][1] << 1) | KeyIn_2;  //按位与,将KeyIn_2的最后一位移入缓冲区。按位与的结果:最后1位是0就移入0,是1就移入1。
  67.     keyBuff[keyOut][2] = (keyBuff[keyOut][2] << 1) | KeyIn_3;  //按位与,将KeyIn_3的最后一位移入缓冲区。按位与的结果:最后1位是0就移入0,是1就移入1。
  68.     keyBuff[keyOut][3] = (keyBuff[keyOut][3] << 1) | KeyIn_4;  //按位与,将KeyIn_4的最后一位移入缓冲区。按位与的结果:最后1位是0就移入0,是1就移入1。
  69.     //更新消抖状态
  70.     for(i = 0; i <= 3 ; i++){
  71.         if((keyBuff[keyOut][i] & 0x0F) == 0x00){
  72.             keyStatus[keyOut][i] = 0;
  73.         }
  74.         else if((keyBuff[keyOut][i] & 0x0F) == 0x0F){
  75.             keyStatus[keyOut][i] = 1;
  76.         }
  77.     }
  78.     //执行下一次的扫描输出
  79.     keyOut++;
  80.     if(keyOut > 4){
  81.         keyOut = 0;
  82.     }
  83.     //根据索引keyOut,释放当前输出引脚,拉低下次的输出引脚。
  84.     switch(keyOut){
  85.         case 0: KeyOut_4 = 1; KeyOut_1 = 0; break;
  86.         case 1: KeyOut_1 = 1; KeyOut_2 = 0; break;
  87.         case 2: KeyOut_2 = 1; KeyOut_3 = 0; break;
  88.         case 3: KeyOut_3 = 1; KeyOut_4 = 0; break;
  89.         default: break;
  90.     }

  91. }
复制代码


问题:其中这段代码放在switch的前面,有一排按键按下,数码管就一直在累加。
虽然keyOut初始值为0,++一次为1,错过了keyOut为0的判断,但是KeyOut加到4的时候,就置0了,下一轮,case0就可以覆盖的到。

  1. //执行下一次的扫描输出
  2. keyOut++;
  3. if(keyOut > 4){
  4. keyOut = 0;
  5. }
复制代码

这段代码放到switch后就ok了,但是逻辑上我 实在不明白为什么放在前面就不可以。求各位大神给指点一下,答疑解惑!


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1034164 发表于 2022-6-12 19:17 | 只看该作者
为了方便格式化 阅读,我生成了代码的图片

回复

使用道具 举报

板凳
ID:213173 发表于 2022-6-13 06:05 | 只看该作者
xcopter 发表于 2022-6-12 19:17
为了方便格式化 阅读,我生成了代码的图片

发生错误的根本原因是代码错误,改变代码位置只是改变发生错误的矩阵行。
错误:if(keyOut > 4)
正确:if(keyOut >= 4) 或 if(keyOut > 3)
回复

使用道具 举报

地板
ID:688692 发表于 2022-6-13 09:02 | 只看该作者
转成就成图看看

回复

使用道具 举报

5#
ID:979299 发表于 2022-6-13 11:54 | 只看该作者
条件表达式语句,动作里面没有包括switchy语句,放到前后都没有作用。
这个格式是java语言写法吧
| 这个管道符在这里是按位或啊
回复

使用道具 举报

6#
ID:275826 发表于 2022-6-13 15:53 | 只看该作者
这个程序代码长,内存大,不好
回复

使用道具 举报

7#
ID:428114 发表于 2022-6-13 17:52 | 只看该作者
// 执行下一次的扫描输出
        keyOut++;
        
       if(keyOut > 4)
       {
            keyOut = 0;
        }
=======================
这个是要给下一次扫描处理的吧?


    switch(keyOut)
   {
    ....
   }
====================
这个switch处理的是keyOut当前值


要先处理当前的,然后再考虑下一个,逻辑要清楚啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表