#include <reg51.h>
#include <intrins.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS=P1^7;
sbit RW=P1^6;
sbit E=P1^5;
uchar code str1[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
uchar code str2[]={0x4e,0x65,0x77,0xfe,0x54,0x65,0x6c,0x4e,0x75,0x6d,0x2e,0x2e,0x2e,0xfe,0xfe,0xfe};
uchar code str3[]={0x49,0x6e,0x70,0x75,0x74,0xfe,0x54,0x65,0x6c,0x4e,0x75,0x6d,0x2e,0x2e,0x2e,0xfe};
uchar keyval=11;
void delayms(uint n)
{
uchar i;
while(n--)
for(i=0;i<113;i++);
}
void check_busy(void)
{
uchar dt;
do
{
dt=0xff;
E=0;
RS=0;
RW=1;
E=1;
dt=P0;
}while(dt&0x80);
E=0;
}
void write_command(uchar com)
{
check_busy();
E=0;
RS=0;
RW=0;
P0=com;
E=1;
_nop_( );
E=0;
delayms(1);
}
void write_data(uchar dat)
{
check_busy();
E=0;
RS=1;
RW=0;
P0=dat;
E=1;
_nop_();
E=0;
delayms(1);
}
void LCD_initial(void)
{
write_command(0x38);
_nop_( );
write_command(0x0C);
_nop_( );
write_command(0x06);
_nop_( );
write_command(0x01);
delayms(2);
}
void write_string(uchar addr,uchar str[])
{
uchar i;
write_command(0x80+addr);
for(i=0;i<strlen(str);i++)
{
write_data(str[i]);
}
}
uchar keyscan()
{
uint row,rol;
P2=0xf0;
if((P2&0xf0)!=0xf0)
{
delayms(20);
if((P2&0xf0)!=0xf0)
{
switch(P2&0xf0)
{
case 0x70:rol=0;break;
case 0xb0:rol=1;break;
case 0xd0:rol=2;break;
case 0xe0:rol=3;break;
}
P2=0x0f;
if((P2&0x0f)!=0x0f)
{
switch(P2&0x0f)
{
case 0x07:row=0;break;
case 0x0b:row=1;break;
case 0x0d:row=2;break;
case 0x0e:row=3;break;
}
while((P2&0x0f)!=0x0f);
keyval=rol*4+row;
}
}
}
return keyval;
}
void main()
{
LCD_initial();
write_string(0x00,str3);
while(1)
{
keyscan();
if(keyval<=9)
{
write_command(0xc0);
write_data(str1[keyval]);
}
if(keyval==10)
{
write_string(0x00,str2);
write_command(0xc0);
write_data(0xfe);
}
}
}
这是我自己在keil5上敲的代码,现在的情况是只显示一位数据,我想让他显示出11位数据后无论怎么按键都没法显示出数据,且按一下按键显示出一位数据
首先需要清楚你使用的是什么类型的LCD屏幕,以及它的显示模式。根据你的代码,应该是16x2字符型LCD屏幕,数据传输方式为8位并行传输。
在程序执行过程中,当检测到按键时,你使用了write_command(0xc0)命令将光标移动到第二行开始的位置,并写入数据。每次按键都会重新写入一位数值,因此只显示一位数据。
如果想要实现输入11位数据后停止显示,可以设置一个计数器,每输入一位数据计数器加1,当计数器累加到11时,停止显示并等待新的输入。在此之前,也需要清空LCD屏幕上的显示内容,可以使用write_command(0x01)命令清屏。
另外,你的程序中keyval变量的初值为11,不适合作为按键扫描函数的返回值。建议将keyval初值设置为255或其他不可能出现的值。在按键扫描函数中,如果没有检测到按键值,则返回该初值。
最后,按键检测函数的时间延迟可以设置得更短,例如5ms,以提高响应速度
#include "123.h"
main()
{
L1602_init();
Delay(100);
UartInit();
while(1)
{
panduan();
}
}
void panduan()
{
if(flag == 0) //判断正转
{
led = 0; //状态灯灭
forward(speed); //电机执行正转且返回速度送给下面进行判断
if(speed == 1) //如果为1 则速度显示为快速
{
LCD_display("Mo Dir: Goto","Mo Spd: Fast ^_^");
}
else if(speed == 3) //如果为3 则速度显示为中速
{
LCD_display("Mo Dir: Goto","Mo Spd: Norl ^_^");
}
else if(speed == 5) //如果为5 则速度显示为慢速
{
LCD_display("Mo Dir: Goto","Mo Spd: Slow ^_^");
}
}
if(flag == 1) //判断反转
{
led = 1; //状态灯亮
back(speed);
if(speed == 1) //电机执行正转且返回速度送给下面进行判断
{
LCD_display("Mo Dir: Back","Mo Spd: Fast ^_^");
}
else if(speed == 3)
{
LCD_display("Mo Dir: Back","Mo Spd: Norl ^_^");
}
else if(speed == 5)
{
LCD_display("Mo Dir: Back","Mo Spd: Slow ^_^");
}
}
}
void Usart() interrupt 4 //中断服务函数
{
uchar n; //定义临时变量
// led = 1;
if(RI) //判断是接收中断产生
{
RI = 0; //标志位清零
n = SBUF; //读入缓冲区的值
switch(n)
{
case'0': //控制正转
flag = 0;
break;
case'1': //控制反转
flag = 1;
break;
case'2': //控制速度为慢
speed = 5;
break;
case'3': //控制速度为中等
speed = 3;
break;
case'4': //控制速度为快
speed = 1;
break;
}
TI = 1;
SBUF = n; //把接收到的值再发回
}
if(TI) //如果是发送标志位,清零
TI = 0;
}