找回密码
 立即注册
楼主: Crystalline

按键扫描优化方法

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:487
  • 最近打卡:2025-05-01 15:22:54
已绑定手机

27

主题

693

回帖

1950

积分

金牌会员

打工人

积分
1950
发表于 2023-12-28 16:52:02 | 显示全部楼层
社区*** 发表于 2023-12-28 16:00
【分享】新型的按键扫描程序 + 累计循环次数。不占用定时器
https://www.stcaimcu.com/forum.php?mod=vie ...

收到,感谢分享
打工人
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:283
  • 最近打卡:2025-04-27 08:07:24

25

主题

159

回帖

304

积分

中级会员

积分
304
发表于 2024-1-17 11:19:12 | 显示全部楼层
用定时器来延时和用 软件延时  那个资源用的少些
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:338
  • 最近打卡:2025-05-01 00:00:50

4

主题

242

回帖

1287

积分

金牌会员

积分
1287
发表于 2024-1-21 15:17:01 | 显示全部楼层
不用定时器的话可以做成非阻塞形式的,在while(1)里面循环检测,比如加个状态机什么的。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:77
  • 最近打卡:2025-04-15 13:59:49

17

主题

61

回帖

575

积分

高级会员

积分
575
发表于 2024-1-31 16:33:29 | 显示全部楼层
鸿哥的帖子告诉我,放到定时器里面去,1ms中断一次,判断20次,消抖
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:403
  • 最近打卡:2025-04-29 08:28:43

12

主题

319

回帖

2017

积分

金牌会员

积分
2017
发表于 2024-1-31 16:59:40 | 显示全部楼层
QW1*** 发表于 2024-1-31 16:33
鸿哥的帖子告诉我,放到定时器里面去,1ms中断一次,判断20次,消抖

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:452
  • 最近打卡:2025-05-01 06:20:50
已绑定手机

13

主题

1257

回帖

2971

积分

金牌会员

积分
2971
发表于 2024-1-31 19:53:32 | 显示全部楼层
QW1*** 发表于 2024-1-31 16:33
鸿哥的帖子告诉我,放到定时器里面去,1ms中断一次,判断20次,消抖

有必要在1ms这么短的中断中判断按键码?会不会时间片太短了?我觉得10-20ms应该比较合理吧,纯技术探讨
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:415
  • 最近打卡:2025-05-01 09:38:35

10

主题

70

回帖

1307

积分

金牌会员

积分
1307
发表于 2024-2-1 22:46:56 | 显示全部楼层
按键扫描最好方式就是放在10ms计时器中断中,因为检测间隔大于按键抖动时间,不需要做消抖检测,而且这种方式不会和其他程序起冲突。其他放在主循环中执行的方式不靠谱,只要再加上其他程序按键扫描时间间隔就会受影响,难道单片机只检查按键别的什么都不做吗?用计时器中断保证了按键检测时间间隔恒定,学会使用定时器中断是复杂变成的基础。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:423
  • 最近打卡:2025-05-01 07:10:25
已绑定手机

76

主题

4833

回帖

8343

积分

超级版主

DebugLab

积分
8343
发表于 2024-2-2 00:15:47 | 显示全部楼层
本帖最后由 DebugLab 于 2024-2-2 00:26 编辑

不使用中断!不使用定时器!不使用延时函数
怎么消抖?用执行其他程序时间消抖!
延时函数坚决不用!!!
放到主循环里一直循环就行,注意一下主循环的频率10~1000Hz都行,中断函数进去必须马上出来,不能进去100ms以上或者死在里面,如果有以固定频率运行的定时器中断,放在里面也行,这个按键扫描程序几乎不耗时。
基本结构:
  1. void Key_Scan(void)
  2. {
  3.         static bit Key_Flag;
  4.         if(KEY==0)
  5.         {
  6.                 if(Key_Flag==1)
  7.                 {
  8.                         Key_Flag=0;
  9.                         //在这里加按下要执行的
  10.                 }
  11.         }
  12.         else
  13.         {
  14.                 if(Key_Flag==0)
  15.                 {
  16.                         Key_Flag=1;
  17.                         //在这里加松开要执行的
复制代码

矩阵键盘因为要切换IO状态读取第二个坐标,需要延时函数消抖,单击双击长按才需要定时器。

矩阵键盘扫描单击双击长按:

  1. #define Init_Up 25 //默认释放时间
  2. #define Init_Down 25 //默认按下时间
  3. #define Init_Long 100 //默认长按时间
  4. #define Init_Disable 1 //默认死区时间
  5. unsigned char Key_Decode(unsigned char temp)
  6. {
  7.         unsigned char key;
  8.         switch(temp)
  9.         {
  10.                 case 0x01:key=0;break;
  11.                 case 0x02:key=1;break;
  12.                 case 0x04:key=2;break;
  13.                 case 0x08:key=3;break;
  14.                 case 0x10:key=4;break;
  15.                 case 0x20:key=5;break;
  16.                 case 0x40:key=6;break;
  17.                 case 0x80:key=7;break;
  18.                 default:key=0xff;
  19.         }
  20.         return key;
  21. }
  22. void Key_Scan(void)
  23. {
  24.         unsigned char temp_x,temp_y;
  25.         X_BUS=0x00;
  26.         Y_BUS=0xff;
  27.         Delay_x10us(100);
  28.         temp_y=Y_BUS;
  29.         if(temp_y!=0xff)
  30.         {
  31.                 temp_y=Y_BUS;
  32.                 X_BUS=0xff;
  33.                 Y_BUS=temp_y;
  34.                 Delay_x10us(100);
  35.                 temp_x=X_BUS;
  36.                 temp_x=Key_Decode(~temp_x);
  37.                 temp_y=Key_Decode(~temp_y);
  38.                 if(temp_x<8&&temp_y<8)
  39.                 {
  40.                         Key=temp_x*8+temp_y;
  41.                         Key_Flag=1;
  42.                 }
  43.                 else
  44.                 {
  45.                         Key_Flag=0;
  46.                         Key=0xff;
  47.                 }
  48.         }
  49.         else
  50.         {
  51.                 Key_Flag=0;
  52.                 Key=0xff;
  53.         }
  54. }
  55. void Clear_Time(bit flag)
  56. {
  57.         TL1=0x00;
  58.         TH1=0x70;
  59.         TR1=flag;
  60. }
  61. void main(void)
  62. {
  63.         Init();        //初始化设置定时器1为不自动重载模式,以20ms为单位,定20ms
  64.                 Temp=IapReadByte(Sector0);
  65.         if(Temp>=5&&Temp<=50)
  66.                 Time_Up=Temp;
  67.         else
  68.         {
  69.                 IapEraseSector(Sector0);
  70.                 IapProgramByte(Sector0,Init_Up);
  71.                 Time_Up=Init_Up;
  72.         }
  73.         Temp=IapReadByte(Sector1);
  74.         if(Temp>=5&&Temp<=50)
  75.                 Time_Down=Temp;
  76.         else
  77.         {
  78.                 IapEraseSector(Sector1);
  79.                 IapProgramByte(Sector1,Init_Down);
  80.                 Time_Down=Init_Down;
  81.         }
  82.         Temp=IapReadByte(Sector2);
  83.         if(Temp>=50&&Temp<=250)
  84.                 Time_Long=Temp;
  85.         else
  86.         {
  87.                 IapEraseSector(Sector2);
  88.                 IapProgramByte(Sector2,Init_Long);
  89.                 Time_Long=Init_Long;
  90.         }
  91.         Temp=IapReadByte(Sector3);
  92.         if(Temp>=1&&Temp<=10)
  93.                 Time_Disable=Temp;
  94.         else
  95.         {
  96.                 IapEraseSector(Sector3);
  97.                 IapProgramByte(Sector3,Init_Disable);
  98.                 Time_Disable=Init_Disable;
  99.         }
  100.         Key_Temp=255;
  101.         while(1)
  102.         {
  103.                 Key_Scan();
  104.                 if(Key_State!=Key_Flag)        //按键状态改变
  105.                 {
  106.                         Key_State=Key_Flag;
  107.                         Clear_Time(1);
  108.                         if(Key_State)        //按下瞬间
  109.                         {
  110.                                 Count_Down=0;
  111.                                 Key_Single=1;
  112.                                 Key_Long=1;
  113.                                 if(Key_Temp==Key)
  114.                                         Key_Double=1;        //和上次一样
  115.                                 else        //和上次不一样
  116.                                 {
  117.                                         Key_Double=0;
  118.                                         Key_Temp=Key;
  119.                                 }
  120.                         }
  121.                         else        //松开瞬间
  122.                         {
  123.                                 Count_UP=0;
  124.                                 Key_Long=0;
  125.                                 if(Key_Single&&Count_Down>Time_Disable&&Count_Down<Time_Down);
  126.                                 else
  127.                                 {
  128.                                         Clear_Time(0);
  129.                                         Key_Single=0;
  130.                                         Key_Double=0;
  131.                                         Key_Long=0;
  132.                                         Key_Temp=0xff;
  133.                                 }
  134.                         }
  135.                 }
  136.                 if(Key_Flag)        //按下
  137.                 {
  138.                         if(Count_UP>=Time_Long&&Key_Long)        //长按
  139.                         {
  140.                                 Send_Key(Key_Temp+128);
  141.                                 Clear_Time(0);
  142.                                 Key_Single=0;
  143.                                 Key_Double=0;
  144.                                 Key_Long=0;
  145.                                 Key_Temp=0xff;
  146.                         }
  147.                 }
  148.                 else        //松开
  149.                 {
  150.                         if(Count_UP>=Time_Up&&Key_Single)        //单击
  151.                         {
  152.                                 Send_Key(Key_Temp);
  153.                                 Clear_Time(0);
  154.                                 Key_Single=0;
  155.                                 Key_Double=0;
  156.                                 Key_Long=0;
  157.                                 Key_Temp=0xff;
  158.                         }
  159.                         if(Count_UP>=Time_Disable&&Count_UP<=Time_Up&&Count_Down>=Time_Disable&&Count_Down<=Time_Down&&Key_Double&&Key_Single)        //双击
  160.                         {
  161.                                 Send_Key(Key_Temp+64);
  162.                                 Clear_Time(0);
  163.                                 Key_Single=0;
  164.                                 Key_Double=0;
  165.                                 Key_Long=0;
  166.                                 Key_Temp=0xff;
  167.                         }
  168.                 }
  169.         }
  170. }
  171. void Timer1_Isr(void) interrupt 3
  172. {
  173.         Count_UP++;
  174.         Count_Down++;
  175.         if(Count_UP>250||Count_Down>250)
  176.         {
  177.                 Count_UP=0;
  178.                 Count_Down=0;
  179.         }
  180. }
复制代码

DebugLab
回复 支持 1 反对 0

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:77
  • 最近打卡:2025-04-15 13:59:49

17

主题

61

回帖

575

积分

高级会员

积分
575
发表于 2024-2-21 16:44:43 | 显示全部楼层
21cns*** 发表于 2024-1-31 19:53
有必要在1ms这么短的中断中判断按键码?会不会时间片太短了?我觉得10-20ms应该比较合理吧,纯技术探讨 ...

1ms 是基础值,意思就是: 定时器1ms 中断一次,然后根据每项任务的需求,累加中断次数,达到一个定时器中断,完成不同的任务要求。比方: 按键是累加10次判断是否按下, LED循环使用累加20次去翻转,移动之类的。  感觉这个用法在要求不高的条件下,还挺省定时器
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:233
  • 最近打卡:2025-04-30 16:08:37

61

主题

818

回帖

1490

积分

金牌会员

积分
1490
发表于 2024-6-5 09:26:50 | 显示全部楼层
myli*** 发表于 2023-12-28 11:15
amobbs里有几个关于按键的帖子挺不错的可以去参考下

{:5_278:} 这论坛还要钱????
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 00:21 , Processed in 0.122642 second(s), 125 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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