找回密码
 立即注册

QQ登录

只需一步,快速开始

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

请教大神分析关于单片机键盘扫描的松手检测程序

[复制链接]
跳转到指定楼层
楼主
ID:578842 发表于 2020-10-30 21:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
学了霖锋的矩阵键盘,(与源程序有差别)程序基本如下:
#include<reg52.h>
#include<intrins.h>
typedef unsigned char u8;
typedef unsigned int  u16;
u8 code smgduan[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,
0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71,};

void delay(u16 z)
{
  u16 x,y;
  for(x=z;x>0;x--)
          for(y=110;y>0;y--);

}


void main()   
{   
        u8 key_l,key_h;
         while(1)
        {           
                P1=0xf0;                 
                key_l=P1;
                if(key_l!=0xf0)
                {
                  delay(10);
                   if(key_l!=0xf0)
                   {
                           key_l=key_l|0x0f;
                        P1=key_l;
                           key_h=P1;
        
                   }
               
                }           
                switch(key_h)
                {
                  case 0xee:P0=~smgduan[15];break;
                  case 0xde:P0=~smgduan[14];break;
                  case 0xbe:P0=~smgduan[13];break;
                  case 0x7e:P0=~smgduan[12];break;
                  case 0xed:P0=~smgduan[11];break;
                  case 0xdd:P0=~smgduan[10];break;
                  case 0xbd:P0=~smgduan[9];break;
                  case 0x7d:P0=~smgduan[8];break;
                  case 0xeb:P0=~smgduan[7];break;
                  case 0xdb:P0=~smgduan[6];break;
                  case 0xbb:P0=~smgduan[5];break;
                  case 0x7b:P0=~smgduan[4];break;
                  case 0xe7:P0=~smgduan[3];break;
                  case 0xd7:P0=~smgduan[2];break;
                  case 0xb7:P0=~smgduan[1];break;
                  case 0x77:P0=~smgduan[0];break;
                }  
          }
}

这个程序没用松手检测,但在开发板上试验,很稳定,没有一次按下是错的。请教各位师傅,为什么呢?
普中的程序如下:
#include<reg52.h>
#include<intrins.h>
typedef unsigned char u8;
typedef unsigned int  u16;
u8 code smgduan[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,
0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71,};
#define smg P0
#define key P1
u8 keyvalue,keyvalue1;


void delay(u16 z)
{
  u16 x,y;
  for(x=z;x>0;x--)
          for(y=110;y>0;y--);

}

void keyscan()
{
  u8 a;
  a=0;
  key=0x0f;
    if(key!=0x0f)
    {
            delay(5);
              if(key!=0x0f)
          {
            switch(key)
            {
            case(0x07):keyvalue=0;break;
            case(0x0b):keyvalue=1;break;
            case(0x0d):keyvalue=2;break;
            case(0x0e):keyvalue=3;break;
            }
          }


    }
    key=0xf0;
    if(key!=0xf0)
    {
            delay(5);
              if(key!=0xf0)
          {
            switch(key)
            {
            case(0x70):keyvalue1=keyvalue;    break;
            case(0xb0):keyvalue1=keyvalue+4;  break;
            case(0xd0):keyvalue1=keyvalue+8;  break;
            case(0xe0):keyvalue1=keyvalue+12; break;
            }
          }
              

    }
   while((a<50)&&(key!=0xf0))        //松手检测且限定时间退出程序
          {
                  delay(5);
                a++;
         
         
          }        //假如按键持续一直按下,会占用CPU的资源,因此设定一定的时间
                //让CPU退出键盘扫描程序
}
void main()   
{
         while(1)
         {
                    keyscan();
                smg=~smgduan[keyvalue1]; //共阳的数码管,要取反。
          }  

}

这个松手检测必须有,不然有时显示不正常。
这两个程序一个没用松手检测,一个用了。但都是正常。
不知道为什么?

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

使用道具 举报

沙发
ID:213173 发表于 2020-10-31 07:18 | 只看该作者
按键松手检测不是必不可少的,要看具体应用场合。楼主上面的示例中,键值是对应唯一1个常数,所以按下不松手,无论按键程序执行多少遍,其键值常量不变。假设带入是变量x++,smgduan[x];,没有松手检测就乱套了。下面是改后的示例,成为松手后0~15随机数了。
typedef unsigned char u8;
typedef unsigned int  u16;
u8 code smgduan[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,
0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71,};
u8 x;
void delay(u16 z)
{
  u16 x,y;
  for(x=z;x>0;x--)
  for(y=110;y>0;y--);

}
void main()   
{   
        u8 key_l,key_h;
        while(1)
        {           
                P1=0xf0;                 
                key_l=P1;
                if(key_l!=0xf0)
                {
                        delay(10);
                        if(key_l!=0xf0)
                        {
                                key_l=key_l|0x0f;
                                P1=key_l;
                                key_h=P1;
                        }
                }           
                x++;
                x%=16;
                switch(key_h)
                {
                        case 0xee:P0=~smgduan[x];break;
                        case 0xde:P0=~smgduan[x];break;
                        case 0xbe:P0=~smgduan[x];break;
                        case 0x7e:P0=~smgduan[x];break;
                        case 0xed:P0=~smgduan[x];break;
                        case 0xdd:P0=~smgduan[x];break;
                        case 0xbd:P0=~smgduan[x];break;
                        case 0x7d:P0=~smgduan[x];break;
                        case 0xeb:P0=~smgduan[x];break;
                        case 0xdb:P0=~smgduan[x];break;
                        case 0xbb:P0=~smgduan[x];break;
                        case 0x7b:P0=~smgduan[x];break;
                        case 0xe7:P0=~smgduan[x];break;
                        case 0xd7:P0=~smgduan[x];break;
                        case 0xb7:P0=~smgduan[x];break;
                        case 0x77:P0=~smgduan[x];break;
                }  
        }
}
回复

使用道具 举报

板凳
ID:234075 发表于 2020-10-31 08:19 | 只看该作者
你应该使用的是数码管显示键值来验证效果,这样是看不出来是否有松手检测效果的。你的程序没有松手检测,表面看是按了一次(按下时间较长),显示也是对应的键值,其实程序是一直在循环并输出这个键值;有了松手检测,则按一次,不管按下时间多长,程序只经过了1次循环,也只输出1次该键值;
在有些场景中必须有松手检测的:
例如一个设备4个按键,分别是开机、关机、累加和累减,明显的开机和关机的按键可以不用松手检测,这个按键就是一个效果,开机或关机,不管按下多少次都无所谓;但是累加和累减就必须有松手检测,他的效果是重复并累计的,如果没有松手检测,你按下一次,会出现累加或累减多次的效果。
回复

使用道具 举报

地板
ID:578842 发表于 2020-10-31 10:46 | 只看该作者
嗯,明白了。谢谢各位的解释。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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