找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 2883|回復(fù): 38
收起左側(cè)

單片機(jī)矩陣按鍵不靈敏有什么好辦法?

  [復(fù)制鏈接]
回帖獎(jiǎng)勵(lì) 5 黑幣 回復(fù)本帖可獲得 5 黑幣獎(jiǎng)勵(lì)! 每人限 1 次
ID:298743 發(fā)表于 2024-5-11 15:54 | 顯示全部樓層 |閱讀模式
我做的是數(shù)碼管顯示時(shí)間的定時(shí)器,用的芯片是STC8H,我有15個(gè)按鍵,開了兩個(gè)中斷了,第一個(gè)定時(shí)器0給了時(shí)鐘計(jì)時(shí),定時(shí)器1給了數(shù)碼管刷新,按鍵檢測(cè)一直放在主函數(shù)循環(huán),嘗試過(guò)開多一個(gè)定時(shí)器2給按鍵掃描,但是還是不靈敏,效果不太明顯。懷疑是延時(shí)的問(wèn)題,但是又想不出什么好辦法解決,畢竟怎么也要消抖,還有給io口反應(yīng)的時(shí)間?纯锤魑淮罄杏惺裁春玫囊庖姟

單片機(jī)源程序如下:
#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口第四位輸出低電平,即行值設(shè)為全0
IO_delay();
if((KEY_MATRIX_PORT&0x56)!=0x56)
{//列值不全為高電平
IO_delay();//去抖動(dòng)
temp=KEY_MATRIX_PORT&0x56;//讀入列值
KEY_MATRIX_PORT=0xA9;//列值設(shè)為低電平
IO_delay();//去抖動(dòng)
temp |= (KEY_MATRIX_PORT&0xA9);//把行值(第四位)和列值(高四位)位或得到唯一指向按鍵的鍵碼
while(KEY_MATRIX_PORT!=0xA9);
}
return temp;
}



主函數(shù)部分:(在16樓)
回復(fù)

使用道具 舉報(bào)

ID:1109793 發(fā)表于 2024-5-11 17:32 | 顯示全部樓層
在一個(gè)定時(shí)器里面,做個(gè)計(jì)時(shí),做個(gè)顯示,做個(gè)按鍵,不行嗎?怎么還要這么多定時(shí)器。
回復(fù)

使用道具 舉報(bào)

ID:123289 發(fā)表于 2024-5-11 20:46 | 顯示全部樓層
中斷服務(wù)程序運(yùn)行時(shí),占用了你的掃描時(shí)間,感覺上按鍵不靈敏。是你的時(shí)序按排不合理!
如果你寫程序能夠設(shè)法不用DELAY()函數(shù)就可以了。DELAY是最低級(jí)初級(jí)編程學(xué)者用的函數(shù)。可用定時(shí)器做延時(shí)啊,用DELAY是浪費(fèi)CPU資源。
回復(fù)

使用道具 舉報(bào)

ID:298743 發(fā)表于 2024-5-12 16:23 | 顯示全部樓層
xiaobendan001 發(fā)表于 2024-5-11 17:32
在一個(gè)定時(shí)器里面,做個(gè)計(jì)時(shí),做個(gè)顯示,做個(gè)按鍵,不行嗎?怎么還要這么多定時(shí)器?

顯示和計(jì)時(shí)一起在同一個(gè)定時(shí)器,顯示程序執(zhí)行得多,會(huì)導(dǎo)致計(jì)時(shí)誤差大吧
回復(fù)

使用道具 舉報(bào)

ID:1109793 發(fā)表于 2024-5-12 16:31 | 顯示全部樓層
asdadqw2 發(fā)表于 2024-5-12 16:23
顯示和計(jì)時(shí)一起在同一個(gè)定時(shí)器,顯示程序執(zhí)行得多,會(huì)導(dǎo)致計(jì)時(shí)誤差大吧

只要你在定時(shí)器中斷時(shí)間里面做完這些事情就不會(huì)影響精度,比如2ms,2ms可以做很多事情了,只要你不用那該死的DELAY
回復(fù)

使用道具 舉報(bào)

ID:1034262 發(fā)表于 2024-5-12 18:39 | 顯示全部樓層
20ms掃描一次按鍵,快到飛起。
回復(fù)

使用道具 舉報(bào)

ID:1109793 發(fā)表于 2024-5-13 07:30 | 顯示全部樓層
coody_sz 發(fā)表于 2024-5-12 18:39
20ms掃描一次按鍵,快到飛起。

20ms太長(zhǎng)了吧,我都是用1ms定時(shí)掃描
回復(fù)

使用道具 舉報(bào)

ID:161164 發(fā)表于 2024-5-13 10:03 | 顯示全部樓層
代碼不全
你只貼了按鍵掃描,沒(méi)貼主循環(huán)
盲猜主循環(huán)有大量代碼
阻塞了按鍵的反應(yīng)
回復(fù)

使用道具 舉報(bào)

ID:298743 發(fā)表于 2024-5-13 13:52 | 顯示全部樓層
lkc8210 發(fā)表于 2024-5-13 10:03
代碼不全
你只貼了按鍵掃描,沒(méi)貼主循環(huán)
盲猜主循環(huán)有大量代碼

主循環(huán)有點(diǎn)長(zhǎng),有兩個(gè)swich判斷,主要是判斷按鍵返回值的
回復(fù)

使用道具 舉報(bào)

ID:298743 發(fā)表于 2024-5-13 13:54 | 顯示全部樓層
yzwzfyz 發(fā)表于 2024-5-11 20:46
中斷服務(wù)程序運(yùn)行時(shí),占用了你的掃描時(shí)間,感覺上按鍵不靈敏。是你的時(shí)序按排不合理!
如果你寫程序能夠設(shè) ...

怎么用定時(shí)器做延時(shí),這個(gè)想法不太懂
回復(fù)

使用道具 舉報(bào)

ID:1120495 發(fā)表于 2024-5-13 14:32 | 顯示全部樓層
xiaobendan001 發(fā)表于 2024-5-13 07:30
20ms太長(zhǎng)了吧,我都是用1ms定時(shí)掃描

10ms我覺得差不多
回復(fù)

使用道具 舉報(bào)

ID:161164 發(fā)表于 2024-5-13 14:38 | 顯示全部樓層
asdadqw2 發(fā)表于 2024-5-13 13:54
怎么用定時(shí)器做延時(shí),這個(gè)想法不太懂

你不弄短主循環(huán)的耗時(shí),用定時(shí)器、中斷也解決不了不靈敏的問(wèn)題
回復(fù)

使用道具 舉報(bào)

ID:1120546 發(fā)表于 2024-5-13 16:41 | 顯示全部樓層
掃描時(shí)間太長(zhǎng)了吧
回復(fù)

使用道具 舉報(bào)

ID:195496 發(fā)表于 2024-5-13 16:53 | 顯示全部樓層
程序思路問(wèn)題,要改進(jìn)
回復(fù)

使用道具 舉報(bào)

ID:844772 發(fā)表于 2024-5-13 17:13 | 顯示全部樓層
12樓說(shuō)的對(duì),你就不是延時(shí)的問(wèn)題,你那點(diǎn)延時(shí)也去不了抖動(dòng)。
回復(fù)

使用道具 舉報(bào)

ID:298743 發(fā)表于 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 計(jì)時(shí)器1 SW1
  21. KeySwitch(0); //按鍵判斷
  22. break;

  23. case 0x3F: //2 計(jì)時(shí)器3 SW3
  24. KeySwitch(2); //按鍵判斷
  25. break;

  26. case 0xF5: //3 計(jì)時(shí)器5 SW5
  27. KeySwitch(4); //按鍵判斷
  28. break;

  29. case 0xFC: //4 溫控設(shè)置鍵 SW13
  30. break;

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

  33. case 0x7B: //6 計(jì)時(shí)器2 SW2
  34. KeySwitch(1); //按鍵判斷
  35. break;

  36. case 0x6F: //7 計(jì)時(shí)器4 SW4
  37. KeySwitch(3); //按鍵判斷
  38. break;

  39. case 0xF3: //8 計(jì)時(shí)器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)) //設(shè)置時(shí)間顯示模式
  49. {
  50. state=2;

  51. }
  52. if((timer==1)&&(ONOFF==1)) //設(shè)置時(shí)間界面End
  53. {
  54. DigdotClose();
  55. state=3;
  56. }
  57. if(timer==2) //關(guān)閉顯示
  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. }
復(fù)制代碼
回復(fù)

使用道具 舉報(bào)

ID:298743 發(fā)表于 2024-5-13 18:25 | 顯示全部樓層
lkc8210 發(fā)表于 2024-5-13 14:38
你不弄短主循環(huán)的耗時(shí),用定時(shí)器、中斷也解決不了不靈敏的問(wèn)題

我上傳了主循環(huán)的代碼,但是我覺得我的主循環(huán)繁瑣,但是執(zhí)行效率應(yīng)該不低,switch語(yǔ)句不是用空間換效率的嗎?望各位大佬解答
回復(fù)

使用道具 舉報(bào)

ID:1109793 發(fā)表于 2024-5-13 19:25 | 顯示全部樓層
asdadqw2 發(fā)表于 2024-5-13 18:25
我上傳了主循環(huán)的代碼,但是我覺得我的主循環(huán)繁瑣,但是執(zhí)行效率應(yīng)該不低,switch語(yǔ)句不是用空間換效率的 ...

在哪兒?
回復(fù)

使用道具 舉報(bào)

ID:298743 發(fā)表于 2024-5-13 20:11 | 顯示全部樓層

好像還沒(méi)審核,我再上傳一次看看
回復(fù)

使用道具 舉報(bào)

ID:844772 發(fā)表于 2024-5-14 09:28 | 顯示全部樓層
Switch沒(méi)耗費(fèi)多少時(shí)間,但我看不到你的子程序,你算算這個(gè) ShowTemp(); 要用多少時(shí)間。
回復(fù)

使用道具 舉報(bào)

ID:23640 發(fā)表于 2024-5-14 09:39 | 顯示全部樓層
while(KEY_MATRIX_PORT!=0xA9);既然都知道用定時(shí)器了,為什么還用這樣的死循環(huán)?不理解
回復(fù)

使用道具 舉報(bào)

ID:1109793 發(fā)表于 2024-5-14 13:28 | 顯示全部樓層
可是調(diào)用不少子程序呢,包括顯示,所以都加一起就慢了,還有樓上說(shuō)的死循環(huán)
回復(fù)

使用道具 舉報(bào)

ID:298743 發(fā)表于 2024-5-14 22:23 | 顯示全部樓層
yaosongjin 發(fā)表于 2024-5-14 09:39
while(KEY_MATRIX_PORT!=0xA9);既然都知道用定時(shí)器了,為什么還用這樣的死循環(huán)?不理解

那這里應(yīng)該怎么編寫,真的不太懂,想不明白
回復(fù)

使用道具 舉報(bào)

ID:298743 發(fā)表于 2024-5-14 22:25 | 顯示全部樓層
glinfei 發(fā)表于 2024-5-14 09:28
Switch沒(méi)耗費(fèi)多少時(shí)間,但我看不到你的子程序,你算算這個(gè) ShowTemp(); 要用多少時(shí)間。

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的都是這樣的程序,最多就循環(huán)6次
回復(fù)

使用道具 舉報(bào)

ID:1109793 發(fā)表于 2024-5-15 08:59 | 顯示全部樓層
asdadqw2 發(fā)表于 2024-5-14 22:25
void ShowNormal()
{
    unsigned char i,temp1,temp2;

LEDbuf為啥這么大?
為啥喜歡大小寫混用?
回復(fù)

使用道具 舉報(bào)

ID:23640 發(fā)表于 2024-5-15 11:39 | 顯示全部樓層
asdadqw2 發(fā)表于 2024-5-14 22:23
那這里應(yīng)該怎么編寫,真的不太懂,想不明白

用if判斷按鍵有沒(méi)有松開呀,掃描按鍵可以放在定時(shí)器里面,每20MS執(zhí)行一次
回復(fù)

使用道具 舉報(bào)

ID:1121518 發(fā)表于 2024-5-20 13:02 | 顯示全部樓層
用延遲1ms就很靈敏
回復(fù)

使用道具 舉報(bào)

ID:1121431 發(fā)表于 2024-5-21 00:16 | 顯示全部樓層
減少定時(shí)掃描周期
回復(fù)

使用道具 舉報(bào)

ID:1121431 發(fā)表于 2024-5-21 00:22 | 顯示全部樓層
ShowTemp(); 確實(shí)一個(gè)都花了這么多時(shí)間了
回復(fù)

使用道具 舉報(bào)

ID:161164 發(fā)表于 2024-5-22 11:06 | 顯示全部樓層
asdadqw2 發(fā)表于 2024-5-13 18:25
我上傳了主循環(huán)的代碼,但是我覺得我的主循環(huán)繁瑣,但是執(zhí)行效率應(yīng)該不低,switch語(yǔ)句不是用空間換效率的 ...

直接在主循環(huán)結(jié)尾加個(gè)引腳取反
用邏輯分析儀或示波器看看取反周期
回復(fù)

使用道具 舉報(bào)

ID:1121849 發(fā)表于 2024-5-22 15:16 | 顯示全部樓層
調(diào)整下觸發(fā)周期或者就把延遲設(shè)置在1ms試試呢
回復(fù)

使用道具 舉報(bào)

ID:1121518 發(fā)表于 2024-5-23 22:08 來(lái)自手機(jī) | 顯示全部樓層
中斷可以用少點(diǎn),因?yàn)闀?huì)占用時(shí)間
回復(fù)

使用道具 舉報(bào)

ID:1123566 發(fā)表于 2024-6-3 18:59 | 顯示全部樓層
調(diào)整中斷時(shí)間
回復(fù)

使用道具 舉報(bào)

ID:925236 發(fā)表于 2024-6-4 19:49 | 顯示全部樓層
你這個(gè)如果是數(shù)碼管實(shí)時(shí)顯示的話是會(huì)有這個(gè)問(wèn)題,解決辦法低級(jí)一點(diǎn)就是把數(shù)碼管消抖延時(shí)改小,高級(jí)一點(diǎn)就不能用延時(shí)函數(shù),用時(shí)間片輪詢
回復(fù)

使用道具 舉報(bào)

ID:1125852 發(fā)表于 2024-6-18 16:03 | 顯示全部樓層
調(diào)整下延遲
回復(fù)

使用道具 舉報(bào)

ID:1125957 發(fā)表于 2024-6-19 09:00 | 顯示全部樓層
八成代碼不對(duì),運(yùn)行時(shí)出錯(cuò),重新編程一下代碼
回復(fù)

使用道具 舉報(bào)

ID:332444 發(fā)表于 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>
復(fù)制代碼

回復(fù)

使用道具 舉報(bào)

ID:1121811 發(fā)表于 2024-6-19 11:08 | 顯示全部樓層
感覺你程序的主循環(huán)里東西太多了
回復(fù)

使用道具 舉報(bào)

ID:1121811 發(fā)表于 2024-6-19 11:09 | 顯示全部樓層
主循環(huán)內(nèi)東西太多了吧
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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