找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1707|回复: 38
收起左侧

单片机矩阵按键不灵敏有什么好办法?

  [复制链接]
回帖奖励 5 黑币 回复本帖可获得 5 黑币奖励! 每人限 1 次
ID:298743 发表于 2024-5-11 15:54 | 显示全部楼层 |阅读模式
我做的是数码管显示时间的定时器,用的芯片是STC8H,我有15个按键,开了两个中断了,第一个定时器0给了时钟计时,定时器1给了数码管刷新,按键检测一直放在主函数循环,尝试过开多一个定时器2给按键扫描,但是还是不灵敏,效果不太明显。怀疑是延时的问题,但是又想不出什么好办法解决,毕竟怎么也要消抖,还有给io口反应的时间。看看各位大佬有什么好的意见。

单片机源程序如下:
#include "key.h"
#include "delay.h"
#include "intrins.h"
void IO_delay(void)
{
_nop_();
_nop_();
_nop_();
}

unsigned char key_scan()
{
unsigned char temp = 0;
KEY_MATRIX_PORT=0x56;//P1口第四位输出低电平,即行值设为全0
IO_delay();
if((KEY_MATRIX_PORT&0x56)!=0x56)
{//列值不全为高电平
IO_delay();//去抖动
temp=KEY_MATRIX_PORT&0x56;//读入列值
KEY_MATRIX_PORT=0xA9;//列值设为低电平
IO_delay();//去抖动
temp |= (KEY_MATRIX_PORT&0xA9);//把行值(第四位)和列值(高四位)位或得到唯一指向按键的键码
while(KEY_MATRIX_PORT!=0xA9);
}
return temp;
}



主函数部分:(在16楼)
回复

使用道具 举报

ID:1109793 发表于 2024-5-11 17:32 | 显示全部楼层
在一个定时器里面,做个计时,做个显示,做个按键,不行吗?怎么还要这么多定时器啊?
回复

使用道具 举报

ID:123289 发表于 2024-5-11 20:46 | 显示全部楼层
中断服务程序运行时,占用了你的扫描时间,感觉上按键不灵敏。是你的时序按排不合理!
如果你写程序能够设法不用DELAY()函数就可以了。DELAY是最低级初级编程学者用的函数。可用定时器做延时啊,用DELAY是浪费CPU资源。
回复

使用道具 举报

ID:298743 发表于 2024-5-12 16:23 | 显示全部楼层
xiaobendan001 发表于 2024-5-11 17:32
在一个定时器里面,做个计时,做个显示,做个按键,不行吗?怎么还要这么多定时器啊?

显示和计时一起在同一个定时器,显示程序执行得多,会导致计时误差大吧
回复

使用道具 举报

ID:1109793 发表于 2024-5-12 16:31 | 显示全部楼层
asdadqw2 发表于 2024-5-12 16:23
显示和计时一起在同一个定时器,显示程序执行得多,会导致计时误差大吧

只要你在定时器中断时间里面做完这些事情就不会影响精度,比如2ms,2ms可以做很多事情了,只要你不用那该死的DELAY
回复

使用道具 举报

ID:1034262 发表于 2024-5-12 18:39 | 显示全部楼层
20ms扫描一次按键,快到飞起。
回复

使用道具 举报

ID:1109793 发表于 2024-5-13 07:30 | 显示全部楼层
coody_sz 发表于 2024-5-12 18:39
20ms扫描一次按键,快到飞起。

20ms太长了吧,我都是用1ms定时扫描
回复

使用道具 举报

ID:161164 发表于 2024-5-13 10:03 | 显示全部楼层
代码不全
你只贴了按键扫描,没贴主循环
盲猜主循环有大量代码
阻塞了按键的反应
回复

使用道具 举报

ID:298743 发表于 2024-5-13 13:52 | 显示全部楼层
lkc8210 发表于 2024-5-13 10:03
代码不全
你只贴了按键扫描,没贴主循环
盲猜主循环有大量代码

主循环有点长,有两个swich判断,主要是判断按键返回值的
回复

使用道具 举报

ID:298743 发表于 2024-5-13 13:54 | 显示全部楼层
yzwzfyz 发表于 2024-5-11 20:46
中断服务程序运行时,占用了你的扫描时间,感觉上按键不灵敏。是你的时序按排不合理!
如果你写程序能够设 ...

怎么用定时器做延时,这个想法不太懂
回复

使用道具 举报

ID:1120495 发表于 2024-5-13 14:32 | 显示全部楼层
xiaobendan001 发表于 2024-5-13 07:30
20ms太长了吧,我都是用1ms定时扫描

10ms我觉得差不多
回复

使用道具 举报

ID:161164 发表于 2024-5-13 14:38 | 显示全部楼层
asdadqw2 发表于 2024-5-13 13:54
怎么用定时器做延时,这个想法不太懂

你不弄短主循环的耗时,用定时器、中断也解决不了不灵敏的问题
回复

使用道具 举报

ID:1120546 发表于 2024-5-13 16:41 | 显示全部楼层
扫描时间太长了吧
回复

使用道具 举报

ID:195496 发表于 2024-5-13 16:53 | 显示全部楼层
程序思路问题,要改进
回复

使用道具 举报

ID:844772 发表于 2024-5-13 17:13 | 显示全部楼层
12楼说的对,你就不是延时的问题,你那点延时也去不了抖动。
回复

使用道具 举报

ID:298743 发表于 2024-5-13 18:23 | 显示全部楼层
  1. while(1)
  2. {
  3. int temp;
  4. SixCountdown();
  5. ForeAlarm();
  6. temp = key_scan();
  7. ShowTemp();
  8. switch(state)
  9. {
  10. case 0:FlagClear();led_hc595_drive(0xff,0xff,0xff,0xff,0x00);break;
  11. case 1:ShowNormal(); EA=1; break;
  12. case 2:ShowSetHMorMS(); DigdotClose(); EA=1; break;
  13. case 3:ShowEnd(); EA=1; break;
  14. case 4:ShowVolume(); EA=1; break;
  15. case 5:ShowAlarm(); EA=1; break;
  16. default:break;

  17. }

  18. switch(temp)
  19. {
  20. case 0x7D: //1 计时器1 SW1
  21. KeySwitch(0); //按键判断
  22. break;

  23. case 0x3F: //2 计时器3 SW3
  24. KeySwitch(2); //按键判断
  25. break;

  26. case 0xF5: //3 计时器5 SW5
  27. KeySwitch(4); //按键判断
  28. break;

  29. case 0xFC: //4 温控设置键 SW13
  30. break;

  31. case 0xCF: //5 温度增加 SW12
  32. break;

  33. case 0x7B: //6 计时器2 SW2
  34. KeySwitch(1); //按键判断
  35. break;

  36. case 0x6F: //7 计时器4 SW4
  37. KeySwitch(3); //按键判断
  38. break;

  39. case 0xF3: //8 计时器6 SW6
  40. KeySwitch(5); //按键判断
  41. break;

  42. case 0xFA: //9 除冰 SW14
  43. break;

  44. case 0xBE: //10 温度减少 SW15
  45. break;

  46. case 0xB7: //11 TIME SW7
  47. timer++;
  48. if((timer==1)&&(ONOFF==0)) //设置时间显示模式
  49. {
  50. state=2;

  51. }
  52. if((timer==1)&&(ONOFF==1)) //设置时间界面End
  53. {
  54. DigdotClose();
  55. state=3;
  56. }
  57. if(timer==2) //关闭显示
  58. {
  59. if(state==3)
  60. {
  61. NumExchange(Hset,Mset,H,M);
  62. }
  63. state=0;
  64. timer =0;
  65. }
  66. break;


  67. case 0xE7: //12 REMINDER SW8
  68. alarm++;
  69. DigdotClose();
  70. BlinkClose();
  71. SetTimerClose();
  72. setHM=0;
  73. if(alarm==1)
  74. {
  75. state=5;
  76. }
  77. if(alarm==2)
  78. {
  79. NumExchange(Halarm1,Malarm1,H,M);
  80. }
  81. if(alarm==3)
  82. {
  83. NumExchange(Halarm2,Malarm2,H,M);
  84. }
  85. if(alarm==4)
  86. {
  87. NumExchange(Halarm3,Malarm3,H,M);
  88. alarm=0;
  89. state=0;
  90. }
  91. break;

  92. case 0xDD: //13 ON/OFF SW9

  93. state1=(state1?0:1);
  94. ONOFF++;
  95. state++;

  96. if(ONOFF==1)
  97. {
  98. state=1;
  99. }

  100. if(ONOFF==2)
  101. {
  102. state=0;
  103. ONOFF=0;
  104. }
  105. break;

  106. case 0xDB: //14 INCREASE SW
  107. increase++;
  108. switch(alarm)
  109. {
  110. case 1: adjustAlarm(Halarm1, Malarm1, Blink, SetTimer, 1); break;
  111. case 2: adjustAlarm(Halarm2, Malarm2, Blink, SetTimer, 1); break;
  112. case 3: adjustAlarm(Halarm3, Malarm3, Blink, SetTimer, 1); break;
  113. default: adjustAlarm(H, M, Blink, SetTimer, 1); break;
  114. }
  115. break;
  116. case 0x9F: //15 DECREASE SW11
  117. decrease++;
  118. switch(alarm)
  119. {
  120. case 1: adjustAlarm(Halarm1, Malarm1, Blink, SetTimer, -1); break;
  121. case 2: adjustAlarm(Halarm2, Malarm2, Blink, SetTimer, -1); break;
  122. case 3: adjustAlarm(Halarm3, Malarm3, Blink, SetTimer, -1); break;
  123. default: adjustAlarm(H, M, Blink, SetTimer, -1); break;
  124. }
  125. break;

  126. default:break;
  127. }
复制代码
回复

使用道具 举报

ID:298743 发表于 2024-5-13 18:25 | 显示全部楼层
lkc8210 发表于 2024-5-13 14:38
你不弄短主循环的耗时,用定时器、中断也解决不了不灵敏的问题

我上传了主循环的代码,但是我觉得我的主循环繁琐,但是执行效率应该不低,switch语句不是用空间换效率的吗?望各位大佬解答
回复

使用道具 举报

ID:1109793 发表于 2024-5-13 19:25 | 显示全部楼层
asdadqw2 发表于 2024-5-13 18:25
我上传了主循环的代码,但是我觉得我的主循环繁琐,但是执行效率应该不低,switch语句不是用空间换效率的 ...

在哪儿?
回复

使用道具 举报

ID:298743 发表于 2024-5-13 20:11 | 显示全部楼层

好像还没审核,我再上传一次看看
回复

使用道具 举报

ID:844772 发表于 2024-5-14 09:28 | 显示全部楼层
Switch没耗费多少时间,但我看不到你的子程序,你算算这个 ShowTemp(); 要用多少时间。
回复

使用道具 举报

ID:23640 发表于 2024-5-14 09:39 | 显示全部楼层
while(KEY_MATRIX_PORT!=0xA9);既然都知道用定时器了,为什么还用这样的死循环?不理解
回复

使用道具 举报

ID:1109793 发表于 2024-5-14 13:28 | 显示全部楼层
可是调用不少子程序呢,包括显示,所以都加一起就慢了,还有楼上说的死循环
回复

使用道具 举报

ID:298743 发表于 2024-5-14 22:23 | 显示全部楼层
yaosongjin 发表于 2024-5-14 09:39
while(KEY_MATRIX_PORT!=0xA9);既然都知道用定时器了,为什么还用这样的死循环?不理解

那这里应该怎么编写,真的不太懂,想不明白
回复

使用道具 举报

ID:298743 发表于 2024-5-14 22:25 | 显示全部楼层
glinfei 发表于 2024-5-14 09:28
Switch没耗费多少时间,但我看不到你的子程序,你算算这个 ShowTemp(); 要用多少时间。

void ShowNormal()
{
    unsigned char i,temp1,temp2;
    for (i = 0; i<6; i++)
        {
                if(AlarmOut==1)
                {
                LEDBuf[i * 4] = 17;
                LEDBuf[i * 4 + 1] = 18;
                LEDBuf[i * 4 + 2] = 10;
                LEDBuf[i * 4 + 3] = alarm;
                }else{
                temp1 = UnitSwitch ? M : H;
                temp2 = UnitSwitch ? S : M;
       
                LEDBuf[i * 4] = temp1 / 10;
                LEDBuf[i * 4 + 1] = temp1 % 10;
                LEDBuf[i * 4 + 2] = temp2 / 10;
                LEDBuf[i * 4 + 3] = temp2 % 10;
                        }
    }

}
有show的都是这样的程序,最多就循环6次
回复

使用道具 举报

ID:1109793 发表于 2024-5-15 08:59 | 显示全部楼层
asdadqw2 发表于 2024-5-14 22:25
void ShowNormal()
{
    unsigned char i,temp1,temp2;

LEDbuf为啥这么大?
为啥喜欢大小写混用?
回复

使用道具 举报

ID:23640 发表于 2024-5-15 11:39 | 显示全部楼层
asdadqw2 发表于 2024-5-14 22:23
那这里应该怎么编写,真的不太懂,想不明白

用if判断按键有没有松开呀,扫描按键可以放在定时器里面,每20MS执行一次
回复

使用道具 举报

ID:1121518 发表于 2024-5-20 13:02 | 显示全部楼层
用延迟1ms就很灵敏
回复

使用道具 举报

ID:1121431 发表于 2024-5-21 00:16 | 显示全部楼层
减少定时扫描周期
回复

使用道具 举报

ID:1121431 发表于 2024-5-21 00:22 | 显示全部楼层
ShowTemp(); 确实一个都花了这么多时间了
回复

使用道具 举报

ID:161164 发表于 2024-5-22 11:06 | 显示全部楼层
asdadqw2 发表于 2024-5-13 18:25
我上传了主循环的代码,但是我觉得我的主循环繁琐,但是执行效率应该不低,switch语句不是用空间换效率的 ...

直接在主循环结尾加个引脚取反
用逻辑分析仪或示波器看看取反周期
回复

使用道具 举报

ID:1121849 发表于 2024-5-22 15:16 | 显示全部楼层
调整下触发周期或者就把延迟设置在1ms试试呢
回复

使用道具 举报

ID:1121518 发表于 2024-5-23 22:08 来自手机 | 显示全部楼层
中断可以用少点,因为会占用时间
回复

使用道具 举报

ID:1123566 发表于 2024-6-3 18:59 | 显示全部楼层
调整中断时间
回复

使用道具 举报

ID:925236 发表于 2024-6-4 19:49 | 显示全部楼层
你这个如果是数码管实时显示的话是会有这个问题,解决办法低级一点就是把数码管消抖延时改小,高级一点就不能用延时函数,用时间片轮询
回复

使用道具 举报

ID:1125852 发表于 2024-6-18 16:03 | 显示全部楼层
调整下延迟
回复

使用道具 举报

ID:1125957 发表于 2024-6-19 09:00 | 显示全部楼层
八成代码不对,运行时出错,重新编程一下代码
回复

使用道具 举报

ID:332444 发表于 2024-6-19 10:28 | 显示全部楼层
  1. if(!k1&&!++Xd)
  2.                 {
  3.                         CKF('S');
  4.                         while(!k1);
  5.                 }
  6.                 if(!k2&&!++Xd)
  7.                 {
  8.                         CKF('X');
  9.                         while(!k2);
  10.                 }
  11.                 if(!k3&&!++Xd)
  12.                 {
  13.                         CKF('L');
  14.                         while(!k3);
  15.                 }
  16.                 if(k1&&k2&&k3)Xd=0;//综合消抖处理
  17.                         
  18. <span style="background-color: rgb(255, 255, 255);">这样的消抖处理够快?代码是否符合逻辑?</span>
复制代码

回复

使用道具 举报

ID:1121811 发表于 2024-6-19 11:08 | 显示全部楼层
感觉你程序的主循环里东西太多了
回复

使用道具 举报

ID:1121811 发表于 2024-6-19 11:09 | 显示全部楼层
主循环内东西太多了吧
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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