关于LCD1602与矩阵按键——按键按下时与按键释放时,效果不一致,且按下时乱码
#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看看是否确实是按下 执行了显示,
建议你这个按键程序这么写:
- while(1)
- {
- t = getkey();
- if(t!=0xff)
- {
- delay(20);
- tt=getkey();
- if((t==tt)&&(t!=0xff))
- {
- while(tt==getkey());
-
- display(1,1,num[t]);
-
- //等待按键松开
- }
- }
- }
看你这显示挺正常的