微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 关于LCD1602与矩阵按键——按键按下时与按键释放时,效果不一致,且按下时乱码

关于LCD1602与矩阵按键——按键按下时与按键释放时,效果不一致,且按下时乱码

时间:10-02 整理:3721RD 点击:
关于LCD1602与矩阵按键——按键按下时与按键释放时,效果不一致,且按下时乱码。向各位前辈取经!主要的功能先介绍一下:当按键按下一个键时,lcd显示相应的数字。下面是代码
#include<reg52.h>       
#define uchar unsigned char
#define uint unsigned int
uchar num[]="0123456789abcdef";
sbit LCD_RS=P2^6;        
sbit LCD_EN=P2^7;
sbit LCD_rw=P2^5;
void delay(uint n)                   //延时
{
                uint i,j;
                for(i=n;i>0;i--)
                for(j=110;j>0;j--);
}
void LCD_write_com(uchar com)           //  写指令函数
{
                LCD_RS=0;               //指令模式       
                P0=com;
                delay(5);               // 通过延时实现数据传输时序
                LCD_EN=1;                         //允许
                delay(5);                            //使能信号持续一定时间高电平
                LCD_EN=0;
                delay(5);
                          
}
void LCD_write_data(uchar dat)
{
                LCD_RS=1;  //数据模式
                P0=dat;
                delay(5);
                LCD_EN=1;       
                delay(5);
                LCD_EN=0;  
                delay(5);
}
void LCD_init()                  //   LCD 设置
{
                LCD_RS=0;               //指令模式       
                LCD_rw=0;
                LCD_write_com(0x38);   //设置16x2显示,5x7点阵,8位数据接口
                LCD_write_com(0x0c);   //00001DCB   D=1开显示 C=1显示光标 B=1光标闪烁
                LCD_write_com(0x06);   //000001NS        N=1/0 光标+1/-1   S=1整屏(N=1)左移(N=0)右移  S=0 不移动
                LCD_write_com(0x01);        //清除屏幕显示
        //        LCD_write_com(0x80);
}
void display(uint x,uint y,uchar dat)  //显示字符函数
{        //y 为 行数选择项  x为显示位置 dat为显示的ASCII码值
                uint address;
                if(y==1)   
                    address=0x80+x;
                else
                                address=0xc0+x;
                LCD_write_com(address);
                LCD_write_data(dat);
}


uchar anasys_key(uchar  serial, uchar rate)
{          
     switch (serial)
     {
           case 0xf7:return(rate+0);
           case 0xfb:return(rate+1);
           case 0xfd:return(rate+2);
           case 0xfe:return(rate+3);
            default:return(0x00);
     }
}

uchar  getkey(void)
{                uint x;
            P1|=0xff;         //高位强制置一
                P1&=0x7f;          // 扫描置零
                if(((x=P1)&0x0f)!=0x0f){x|=0x80;return(anasys_key(x,0));}
                P1|=0xff;
                P1&=0xBf;
                if(((x=P1)&0x0f)!=0x0f){x|=0x40;return(anasys_key(x,4));}
                P1|=0xff;
                P1&=0xDf;
                if(((x=P1)&0x0f)!=0x0f){x|=0x20;return(anasys_key(x,8));}
                P1|=0xff;
                P1&=0xEf;
                if(((x=P1)&0x0f)!=0x0f){x|=0x10;return(anasys_key(x,12));}
}

void main()
{
        uchar t,tt;
        delay(400);
        LCD_init();
//        LCD_write_com(0x88);
        display(0,1,' ');

                while(1)
                {
                 t=getkey();
                 
                 delay(20);     /*防抖动*/
                 tt=getkey();
                 if((t==tt)&&(t!=0xff))
               {
                 while(tt==getkey());
                           
                display(1,1,num[t]);
                 
                 //等待按键松开
               }
            }
}
这是按下时的图像


这是释放时的图像





问题主要在按键扫描程序,键值不能锁定。修改如下:
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit LCD_RS=P2^6;        
sbit LCD_EN=P2^7;
sbit LCD_rw=P2^5;
uchar num[]="0123456789abcdefg_";
uchar key=16;                                                        //键值变量
/*******100us延时程序********/
void delay(uint x)
{
        uint a,b;
        for(a=x;a>0;a--)
                for(b=10;b>0;b--);
}
/*******1602液晶屏写指令程序********/
void write_com(uchar com)
{
        LCD_EN=0;        //初始设置LCD_EN低电平
        LCD_RS=0;        //允许写指令
        P0=com;                //传递指令
        delay(10);        //延时1ms
        LCD_EN=1;        //使能写入
        delay(10);        //延时1ms
        LCD_EN=0;        //低跳变执行
       
}
/*******1602液晶屏写数据程序********/
void write_date(uchar date)
{
        LCD_EN=0;        //初始设置LCD_EN低电平
        LCD_RS=1;        //允许写数据
        P0 =date;        //传递数据
        delay(10);        //延时1ms
        LCD_EN=1;        //使能写入
        delay(10);        //延时1ms
        LCD_EN=0;        //低跳变执行
       
}
/*******1602液晶屏初始化程序********/
void init()                //设置显示模式、
{
        LCD_rw=0;
        write_com(0x38);//设置16*2显示,5*7点阵,8位数据接口
        write_com(0x01);//显示清零,数据指针清零
//        write_com(0x0f);//设置开显示,显示光标,光标闪烁
//        write_com(0x0e);//设置开显示,显示光标,光标不闪
        write_com(0x0c);//设置开显示,不显光标
        write_com(0x06);//设置写一个字符后地址指针加1
//        write_com(0x07);//设置写一个字符后整屏左移
        write_com(0x80);//数据指针初始化,设置显示初始位置
}
void display(uint x,uint y,uchar dat)  //显示字符函数
{//y 为 行数选择项  x为显示位置 dat为显示的ASCII码值
        uint address;
        write_com(0x01);
        if(y==1)   
                address=0x80+x;
        else
                address=0xc0+x;
        write_com(0x01);
        write_com(address);
        write_date(dat);
}
void key_scan()                                                        //矩阵键盘扫描函数
{
        uchar temp1,temp2,temp3;                        //临时变量
        static bit sign=0;                                        //按键自锁标志
        static uchar count=0;                                //消抖计数变量
        P1=0xf0;                                                        //先给P1赋一个初值
        if(P1!=0xf0)                                                 //判断P1不等于所赋初值,说明有健按下
        {
                if(sign==0)                                                //如果按键自锁标志=0
                {
                        count++;                                        //主循环消抖计数
                        if(count>=100)                                //消抖计数自>=100
                        {
                                count=100;                                //防止溢出
                                sign=1;                                        //按键自锁标志置1,键不抬起,按其他键无效
                                temp1=P1;                                //temp1反映高4位变化
                                P1=0x0f;                                //再给P1赋值0x0f
                                temp2=P1;                                //temp2反映低4位变化
                                temp3=temp2|temp1;                //temp3=高4位+低4位
                                switch(temp3)
                                {
                                        case 0xee: key= 0; break;
                                        case 0xde: key= 1; break;
                                        case 0xbe: key= 2; break;
                                        case 0x7e: key= 3; break;
                                        case 0xed: key= 4; break;
                                        case 0xdd: key= 5; break;
                                        case 0xbd: key= 6; break;
                                        case 0x7d: key= 7; break;
                                        case 0xeb: key= 8; break;
                                        case 0xdb: key= 9; break;
                                        case 0xbb: key=10; break;
                                        case 0x7b: key=11; break;
                                        case 0xe7: key=12; break;
                                        case 0xd7: key=13; break;
                                        case 0xb7: key=14; break;
                                        case 0x77: key=15; break;
                                }
                                display(0,1,num[key]);//显示键值
                        }
                }
        }
        else                                                                         //按键抬起
        {
                sign=0;                                                                //按键自锁标志清0
                count=0;                                                        //消抖计数清0
        }
}
void main()
{
        init();
        write_com(0x88);
        display(0,1,num[key]);
        while(1)
        {
                key_scan();
        }
}

如何能够自己控制按下时 显示的字符或者说 如何保持 按下与释放时字符一致

首先,你这个按键检测的程序不标准,其次,按下按键可以显示 东西,说明,按下的那一刻,执行了
display(1,1,num[t]);
那么这个问题就好排查了,自己在研究一下,可以在这句话下面加个蜂鸣器或者LED看看是否确实是按下 执行了显示,
建议你这个按键程序这么写:

  1. while(1)
  2. {
  3.   t = getkey();
  4.   if(t!=0xff)
  5.   {
  6.         delay(20);
  7.         tt=getkey();
  8.         if((t==tt)&&(t!=0xff))
  9.         {
  10.              while(tt==getkey());
  11.                            
  12.                 display(1,1,num[t]);

  13.                  
  14.                  //等待按键松开

  15.                }
  16.   }
  17. }

复制代码

看你这显示挺正常的

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top