为何LCD1602在仿真上能显示,在硬件上不能显示。
时间:10-02
整理:3721RD
点击:
各位大神,LCD1602为何在仿真上能显示,在硬件上不能显示,求助啊。
线路连接没有问题,也不存在背光问题。,
各位大神,帮我支支招。
程序如下:
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define ulong unsigned long
#define uint unsigned int
uchar idata welcome[16]={" clock "}; //定义第一行显示数组
uchar idata lwelcome[16]={" clock "}; //定义第一行显示数组
uchar idata llwelcome[16]={" clock "}; //定义第一行显示数组
uchar idata lllwelcome[16]={" clock "}; //定义第一行显示数组
uchar idata sslcdtimer[16]={" 00:00:00 "};
uchar idata tsslcdtimer[16]={" 00:00:00 "};
uchar idata lcdtimer[16]={" 00:00:00 "}; //定义第二行显示数组
uchar idata mlcdtimer[16]={" 00: : "}; //定义第二行显示数组
uchar idata hlcdtimer[16]={" :00: "}; //定义第二行显示数组
uchar idata setlcdtimer[16]={" 00:01:00 "};
uchar timecount;
uchar temps;
bit timeflag;
bit sstimeflag;
sbit ring=P2^0;//蜂鸣闹铃
sbit e=P2^7;//LCD显示器E
sbit rw=P2^6;//LCD显示器RW
sbit rs=P2^5;//LCD显示器RS
sbit P10=P1^0; //测试用闪灯
sbit Key=P3^2;//秒表暂停,清零
sbit Key0=P3^3;//调时,设定闹钟时间,秒表选择
sbit Key1=P3^4;//调时,设定闹钟时间改变
uchar th1_f; //在中断中装载的T0的值高8位
uchar tl1_f; //在中断中装载的T0的值低8位
uint m=0;
uint n=0;
ulong i;
uint f=0,g=1;
uint j,k;
uchar code freq[3][14]=
{
{0xF2,0x42,
0xF3,0xC1,
0xF5,0x17,
0xF5,0xB6,
0xF6,0xD0,
0xF7,0xD1,
0xF8,0xB6},
{0xF9,0x21,
0xF9,0xE0,
0xFA,0x8B,
0xFA,0xD7,
0xFB,0x68,
0xFB,0xE8,
0xFC,0x5B },
{0xFC,0x8D,
0xFC,0xEE,
0xFD,0x44,
0xFD,0x6D,
0xFD,0xB4,
0xFD,0xF4,
0xFE,0x2D},
}; //音乐频率表,低音,中音,高音,系统振荡频率11.0592MHz
uint code song1[]={26,25,23,25,31,26,25,26,23,25,26,25,23,22,21,16,25,23,22,22,23,23,23,26,23,22,21,25,23,22,21,16,21,15,26,25,23,25,31,26,25,26,23,25,26,25,23,22,21,16,25,23,22,22,23,23,23,26,23,22,21,25,23,22,21,16,21,15};
//编制音乐
//**************************************************
//软件延时函数(系统晶振为11.0592MHz),延时时间约为40μs
//入口条件:无符号整型变量del1,最终的延时时间为(del1*40)μs
//**************************************************
void delay(uint del1)
{
uchar del2;
for(;del1>0;del1--)
for(del2=10;del2>0;del2--);
}
//**************************************************
//液晶显示器判忙函数
//**************************************************
void busy()
{
uchar temp;
temp=0x00;
rs=0;
rw=1;
while((temp&0x80)==0x80)
{
P0=0xff;
e=1;
temp=P0;
e=0;
}
}
//**************************************************
//向液晶显示器写命令函数
//**************************************************
void WR_Com(uchar temp)
{
busy();
rs=0;
rw=0;
P0=temp;
e=1;
e=0;
}
//**************************************************
//向液晶显示器写数据函数
//**************************************************
void WR_Data(uchar num)
{
busy();
rs=1;
rw=0;
P0=num;
e=1;
e=0;
}
//**************************************************
//向液晶显示器写入显示数据函数
//入口条件:液晶显示器行首地址(指示第一行还是第二行)和待显示数组的首地址
//**************************************************
//void disp_lcdchar(uchar addr,uchar temp1)
//{
// WR_Com(addr);
// delay(100);
// WR_Data(temp1);
//}
void disp_lcd(uchar addr,uchar *temp1)
{
uchar i;
WR_Com(addr);
delay(100);
for(i=0;i<16;i++)
{
WR_Data(temp1);
delay(100);
}
}
//**************************************************
//液晶显示器初始化函数
//**************************************************
void lcd_ini()
{
char i;
for(i=3;i>0;i--)
{
P0=0x30;
rs=0;
rw=0;
e=1;
e=0;
delay(100);
}
P0=0x38;
rs=0;
rw=0;
e=1;
e=0;
delay(100);
}
//**************************************************
//液晶显示器复位函数
//**************************************************
void lcd_Reset()
{
WR_Com(0x01);
delay(100);
WR_Com(0x06);
delay(100);
WR_Com(0x0c);
delay(100);
}
//**************************************************
//外部中断函数,秒表暂停,清零
//**************************************************
void modess() interrupt 0 using 0
{
delay(10000);
n++;
if(n==3)
n=0;
}
//**************************************************
//外部中断函数,模式选择
//**************************************************
void modepp() interrupt 2 using 1
{
delay(30000);
m++;
if(m==6)
n=0;
if(m==7)
m=0;
}
//**************************************************
//定时/计数器中断函数,1S及0.01S
//**************************************************
void timer0() interrupt 1 using 2
{
TH0=0xdc;
TL0=0x23;
sstimeflag=1;
if(--timecount==0)
{
timecount=100;
timeflag=1;
}
}
//**************************************************
//定时/计数器中断函数,装入音乐频率计数初值
//**************************************************
void timer1() interrupt 3 using 3
{
TL1=tl1_f;TH0=th1_f; //调入预定时值
ring=!ring; //取反音乐输出IO
}
//**************************************************
//主函数
//**************************************************
void main()
{
P10=1;
lcd_ini();
lcd_Reset();
/* for(i=0;i<10;i++)
{
temps=welcome;
disp_lcdchar(0x80+1,temps); //LCD 单字符从左到右显示
delay(10000);
}*/
disp_lcd(0x80,welcome);
delay(10000);
disp_lcd(0x80,lwelcome);
delay(10000);
disp_lcd(0x80,llwelcome);
delay(10000);
disp_lcd(0x80,lllwelcome);
delay(10000);
disp_lcd(0x80,llwelcome);
delay(10000);
disp_lcd(0x80,lwelcome);
delay(10000);
disp_lcd(0x80,welcome); //LCD滚动显示
delay(10000);
disp_lcd(0xc0,lcdtimer);
P10=0;
TMOD=0x11;
TH0=0xdc;
TL0=0x23;
TR0=1;
IE=0x86;
timeflag=0; //1秒计时标志
sstimeflag=0; //0.01秒计时标志
timecount=100;
while(1)
{
while(m==6)//秒表
{
IE=0x87;
if(n==0) //秒表跑动
{
if(sstimeflag==1)
{
sstimeflag=0;
sslcdtimer[11]+=1;
if(sslcdtimer[11]>=0x3a)
{
sslcdtimer[11]=0x30;
sslcdtimer[10]+=1;
if(sslcdtimer[10]>=0x3a)
{
sslcdtimer[10]=0x30;
sslcdtimer[8]+=1;
if(sslcdtimer[8]>=0x3a)
{
sslcdtimer[8]=0x30;
sslcdtimer[7]+=1;
if(sslcdtimer[7]>=0x36)
{
sslcdtimer[7]=0x30;
}
}
}
}
disp_lcd(0xc0,sslcdtimer);
}
if(n==1)//秒表暂停
{
disp_lcd(0xc0,sslcdtimer);
}
if(n>=2)//秒表清零
{
disp_lcd(0xc0,tsslcdtimer);
for(i=0;i<16;i++)
sslcdtimer=tsslcdtimer;
}
}
}
while(m==0||m>=3) //时钟程序,只要不是调时,就一直运行
{
IE=0x86;
if(timeflag==1)
{
timeflag=0;
lcdtimer[11]+=1;
if(lcdtimer[11]>=0x3a)
{
lcdtimer[11]=0x30;
lcdtimer[10]+=1;
if(lcdtimer[10]>=0x36)
{
lcdtimer[10]=0x30;
lcdtimer[8]+=1;
if(lcdtimer[8]>=0x3a)
{
lcdtimer[8]=0x30;
lcdtimer[7]+=1;
if(lcdtimer[7]>=0x36)
{
lcdtimer[7]=0x30;
lcdtimer[5]+=1;
if(lcdtimer[5]>=0x3a)
{
lcdtimer[5]=0x30;
lcdtimer[4]+=1;
if(lcdtimer[4]>=0x33&&lcdtimer[5]>=0x35)
{
lcdtimer[5]=0x30;
lcdtimer[4]=0x30;
}
}
}
}
}
}
}
if(m==0)
{
disp_lcd(0xc0,lcdtimer);
if(!Key1)//关掉闹钟
{
g=0;
}
if(lcdtimer[8]==setlcdtimer[8]&&lcdtimer[7]==setlcdtimer[7]&&lcdtimer[5]==setlcdtimer[5]&&lcdtimer[4]==setlcdtimer[4])
f=1; //开启闹钟 ,播放音乐
if(f&&g)
{
/*ring=1;
delay(10000);
ring=0;
f=0; */
IE=0x8e;
j=song1/10-1;
k=2*(song1%10-1);
th1_f=freq[j][k]; //取出对应的定时值送给T0
tl1_f=freq[j][++k];
TR1=1;
for(n=0;n<50000;n++); //音符间延时
i++;
TR1=0;
f=0;
}
}
}
while(m==1) //调时分
{
if(!Key1)
{
delay(10000);
timeflag=0;
lcdtimer[8]+=1;
if(lcdtimer[8]>=0x3a)
{
lcdtimer[8]=0x30;
lcdtimer[7]+=1;
if(lcdtimer[7]>=0x36)
{
lcdtimer[7]=0x30;
}
}
}
disp_lcd(0xc0,lcdtimer);
delay(8000);
mlcdtimer[11]=lcdtimer[11];
mlcdtimer[10]=lcdtimer[10];
mlcdtimer[5]=lcdtimer[5];
mlcdtimer[4]=lcdtimer[4];
disp_lcd(0xc0,mlcdtimer);
}
while(m==2) //调时时
{
if(!Key1)
{
delay(10000);
lcdtimer[5]+=1;
if(lcdtimer[5]>=0x3a)
{
lcdtimer[5]=0x30;
lcdtimer[4]+=1;
}
if(lcdtimer[4]==0x32&&lcdtimer[5]>=0x34)
{
lcdtimer[5]=0x30;
lcdtimer[4]=0x30;
}
}
disp_lcd(0xc0,lcdtimer);
delay(8000);
hlcdtimer[11]=lcdtimer[11];
hlcdtimer[10]=lcdtimer[10];
hlcdtimer[8]=lcdtimer[8];
hlcdtimer[7]=lcdtimer[7];
disp_lcd(0xc0,hlcdtimer);
}
while(m==3)//显示闹铃时间
{
if(!Key1)
{
delay(10000);
}
disp_lcd(0xc0,setlcdtimer);
}
while(m==4) //调闹铃分
{
if(!Key1)
{
delay(10000);
setlcdtimer[8]+=1;
if(setlcdtimer[8]>=0x3a)
{
setlcdtimer[8]=0x30;
setlcdtimer[7]+=1;
if(setlcdtimer[7]>=0x36)
{
setlcdtimer[7]=0x30;
}
}
}
disp_lcd(0xc0,setlcdtimer);
delay(8000);
mlcdtimer[11]=setlcdtimer[11];
mlcdtimer[10]=setlcdtimer[10];
mlcdtimer[5]=setlcdtimer[5];
mlcdtimer[4]=setlcdtimer[4];
disp_lcd(0xc0,mlcdtimer);
}
while(m==5)//调闹铃时
{
if(!Key1)
{
delay(10000);
setlcdtimer[5]+=1;
if(setlcdtimer[5]>=0x3a)
{
setlcdtimer[5]=0x30;
setlcdtimer[4]+=1;
}
if(setlcdtimer[4]==0x32&&setlcdtimer[5]>=0x34)
{
setlcdtimer[5]=0x30;
setlcdtimer[4]=0x30;
}
}
disp_lcd(0xc0,setlcdtimer);
delay(8000);
hlcdtimer[11]=setlcdtimer[11];
hlcdtimer[10]=setlcdtimer[10];
hlcdtimer[8]=setlcdtimer[8];
hlcdtimer[7]=setlcdtimer[7];
disp_lcd(0xc0,hlcdtimer);
}
}
软件仿真不是万能,像你这个问题,只能自己去找,别人还真难帮到你的。
出现这样的问题,就要一个个排查,先从你的LCD函数看有没问题,看能不能有显示的时候再去加入你的闹钟之类的东西吧,个人感觉比较大的可能性是你的LCD的时序还不对。软件仿真时的时序跟硬件上的时序还是有小差别的,对照着规格书上的时序去排查吧
一般是硬件问题 最好结合硬件原理图的方式进行查错
仿真和实际电路有时候是有区别的,不能完全依赖仿真判断设计是否正确;
你这个问题我判断是由于时序不能满足1602造成的,你每次在对R/W、E、RS操作后加一条或两条空操作,应该能解决问题。