[单片机类] 【一个小小的个人经验分享】【四】按键+数码管

[复制链接]
 楼主| enderman1 发表于 2019-2-10 20:25 | 显示全部楼层 |阅读模式
说在前面的话:亲戚这可算走完了,不知道小伙伴们过年忙完没有啊?
说起按键,总会让人头疼,它似乎是一个非常玄学的东西;也是历年来蓝桥杯单片机比赛的一个重难点。

对于蓝桥杯开发板而言,按键分为矩阵按键独立按键两种,矩阵按键比独立按键难自然不多说,而一般情况下省赛期间补考矩阵按键但是还是能难倒一大批人;其主要原因在于一个按键可以有不同的功能,如果想要增加难度的话比赛也可以出长短按键也说不定;总之按键这个东西想出难可以使整个题目瞬间上升一个难度,但是其归根结底无非是对IO口状态的读取,但是却能灵活的运用到各个地方,因此平常的多多练习是必不可少的。

好了,言归正传,对于独立按键与其它外设的结合,我总结了几种方法:

1、传统方案——软件消抖or松手检测


  1. //软件消抖一般实现方法
优点:可以大概实现按键消抖的效果
缺点:使用软件延时浪费CPU时间、而且长按不丢的话可能影响数码管显示

  1. //松手检测一般实现方法
  2. sbit key1=P3^0;
  3. if(key1==0){
  4.       num++;
  5. }while(!key1);
优点:按着不丢的时候数据不会一直增加(如果是题目有要求的话另当别论)
缺点:按着不丢的时候动态扫描数码管不正常显示

当然也有第三种写法,就是软件消抖和松手检测写在一起的写法,但是似乎都解决不了手一直按着的问题(要么数据一直快速自加、要么数码管不正常显示);


因此我自己想了一个办法,谈不上多好,但是可以有效的解决这个问题,至少在实现效果来说是可以的。


2、改进方案

  1. //改进方法
  2. sbit key1=P3^0;
  3. if(key1==0){
  4.     delay_ms(5);
  5. if(key1==0){
  6.     num++;
  7. }
  8. }while(!key1){display();}


没错,就是在原有while(!key1)的里面添加了display();也就是数码管显示的函数;这可能有点操作系统的思想(开玩笑的了,比不上),也就是说,按键按下的时候,while是一直在循环的,也就是说CPU算是一直干等着,什么也没有干,因此你的动态扫描数码管显示当然无法正常显示了,所以基于这个的缺陷,while里面不能干等;在等的同时也要维持数码管的显示,这就保证了按下不丢的时候你的显示效果不受影响,说不定验分的时候这个实现效果也是一个添分项   你说是不是。。。但是,要知道,仅仅是维持数码管的显示,数据当然也就停止了(外设犹如DS1302什么的不会受影响的了~)

至于矩阵按键也是同样的道理,以下是矩阵按键的程序(直接复制我当年写的吧),谈不上多好,但是可以用。。

3、矩阵按键

其实对于矩阵按键,网上的方法层出不穷,有心的话一搜就能搜出一大堆教程+例程,所以我也在此不多费**,比较我也是用的人家的方法嘛。。。

  1. unsigned char keyscan(){
  2.         unsigned char key_value;
  3.         unsigned char key_num;

  4.         P3=0x7f;
  5.         P44=0;P42=1;
  6.         key_value=P3;
  7.         key_value&=0x0f;
  8.         if(key_value!=0x0f){        
  9.                 key_value=P3;
  10.                 switch(key_value){
  11.                         case 0x7e:key_num=1;break;
  12.                         case 0x7d:key_num=2;break;
  13.                         case 0x7b:key_num=3;break;
  14.                         case 0x77:key_num=4;break;
  15.                         default:key_num=0x00;
  16.                 }
  17.         }
  18.         //====================================
  19.         P3=0xbf;
  20.         P44=1;P42=0;
  21.         key_value=P3;
  22.         key_value&=0x0f;
  23.         if(key_value!=0x0f){        
  24.                 key_value=P3;
  25.                 switch(key_value){
  26.                         case 0xbe:key_num=5;break;
  27.                         case 0xbd:key_num=6;break;
  28.                         case 0xbb:key_num=7;break;
  29.                         case 0xb7:key_num=8;break;
  30.                         default:key_num=0x00;
  31.                 }
  32.         }
  33.         //====================================
  34.         P3=0xdf;
  35.         P44=1;P42=1;
  36.         key_value=P3;
  37.         key_value&=0x0f;
  38.         if(key_value!=0x0f){        
  39.                 key_value=P3;
  40.                 switch(key_value){
  41.                         case 0xde:key_num=9;break;
  42.                         case 0xdd:key_num=10;break;
  43.                         case 0xdb:key_num=11;break;
  44.                         case 0xd7:key_num=12;break;
  45.                         default:key_num=0x00;
  46.                 }
  47.         }
  48.         //====================================
  49.         P3=0xef;
  50.         P44=1;P42=1;
  51.         key_value=P3;
  52.         key_value&=0x0f;
  53.         if(key_value!=0x0f){        
  54.                 key_value=P3;
  55.                 switch(key_value){
  56.                         case 0xee:key_num=13;break;
  57.                         case 0xed:key_num=14;break;
  58.                         case 0xeb:key_num=15;break;
  59.                         case 0xe7:key_num=16;break;
  60.                         default:key_num=0x00;
  61.                 }
  62.         }

  63.         return key_num;
  64. }


采用的是比较传统的方式,如果想写成上方的改进版也是可以的,原理都是一样的;至于P44 和  P42  在完整电路分析的时候我似乎已经提到,它们分别代替了传统单片机的P37   和  P36



那么今天的内容就到这里的,下次见。。。。



xyz549040622 发表于 2019-2-10 20:29 | 显示全部楼层
支持下,谢谢分享!从刚开始入门的时候使用状态机,是个很好的习惯。

评论

一看评论就知道肯定是老江湖了,哈哈,多谢支持  发表于 2019-2-10 20:50
换专业的娃 发表于 2019-3-22 11:09 | 显示全部楼层
支持支持
lihui567 发表于 2019-5-31 23:36 | 显示全部楼层
新手来说入门学习很好,采用按键扫描,后续可以写成按键驱动
妄言之半! 发表于 2020-1-13 12:57 | 显示全部楼层
while(!key1)什么意思啊,while 语句不是条件为真才会执行下面的语句吗,当按键按下的时候,条件为真,然后取反不就是条件为假了吗,怎么还会执行下面的语句啊?

评论

按键另一端是接地的,按下的时候是0,取反之后是1  发表于 2020-1-29 17:33
思难忘 发表于 2020-4-6 11:27 | 显示全部楼层
学习了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

71

帖子

12

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

11

主题

71

帖子

12

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