这两天想用AT89C2051+LCD1602做点东西,本着节省管脚的原则,想用4位控制,按照LCD1602的手册上说的把在自己的Cepark51实验板(以下简称51实验板)上8位正常的程序的初始化部分和写指令和数据部分改了一下,结果在51实验板无显示,原程序如下:
//Cepark51实验板LCD1602显示程序
//日期:2008年8月20日 四位控制
//文件名:lcd1602_c.c
//作者:yanwuxu
#include "at89x51.h"
#define uchar unsigned char
#define uint unsigned int
#define lcd_bus P0 //lcd1602 数据总线
sbit lcd_rs=P1^0; //lcd1602 数据/命令选择端,1数据,0指令
sbit lcd_rw=P1^1; //lcd1602 读写控制端,1读,0写
sbit lcd_en=P1^2; //lcd1602 使能端,高脉冲有效
void Delay1ms(uint mDelay1) //1ms延时
{
uint mDelay2;
for(;mDelay1>0;mDelay1--)
{ for(mDelay2=0;mDelay2<114;mDelay2++)
{;}
}
}
void lcd_wdata(uchar lcd_data) //lcd1602写数据
{
lcd_bus=lcd_data; //先送高4位
lcd_rs=1;
lcd_rw=0;
lcd_en=0;
Delay1ms(3);
lcd_en=1;
// Delay1ms(1);
lcd_bus=(lcd_data<<=4); //再送低4位
lcd_rs=1;
lcd_rw=0;
lcd_en=0;
Delay1ms(3);
lcd_en=1;
}
void lcd_wcmd(uchar lcd_cmd) //lcd写指令
{
lcd_bus=lcd_cmd;
lcd_rs=0;
lcd_rw=0;
lcd_en=0;
Delay1ms(3);
lcd_en=1;
// Delay1ms(1);
lcd_bus=(lcd_cmd<<=4);
lcd_rs=0;
lcd_rw=0;
lcd_en=0;
Delay1ms(3);
lcd_en=1;
}
void lcd_disp_byte(uchar x,uchar y,uchar lcd_dat) //lcd写字符,x横位置1-16,y行,y为1为显示在第一行,其它的为显示在第2行
{
uchar lcd_address;
if(y==1)
lcd_address=0x80+x-1; //从1-16
else
lcd_address=0xc0+x-1; //从1-16
lcd_wcmd(lcd_address);
lcd_wdata(lcd_dat);
}
void lcd_disp_str(uchar x,uchar y,uchar code *s) //lcd写字符串,x横位置1-16,y行,y为1为显示在第一行,其它的为显示在第2行
{
uchar lcd_address;
if(y==1)
lcd_address=0x80+x-1; //从1-16
else
lcd_address=0xc0+x-1; //从1-16
lcd_wcmd(lcd_address);
while(*s>0)
{
lcd_wdata(*s);
s++;
};
}
void lcd_init() //lcd初始化
{
Delay1ms(15); //延时15ms
lcd_wcmd(0x28); //4位是0x28,8位是0x38
Delay1ms(15);
lcd_wcmd(0x28);
Delay1ms(15);
lcd_wcmd(0x28);
lcd_wcmd(0x0c);
lcd_wcmd(0x06);
lcd_wcmd(0x01);
}
void main()
{
lcd_init();
while(1)
{
lcd_disp_byte(3,1,'K'); //测试
lcd_disp_str(4,2,"123456");
}
}
后来在网上查阅了别人的一些关于4位驱动的文章,在LCD初始化部分0x28之前再加入0x02这条这条指令(LCD1602的归位指令),编译下载后开机显示正常了,但奇怪的是按复位键后显示不对,显示的现象就像是初始化没好一样,上面一行显示一排黑块,搞了一下午没明白为什么,问了几个兄弟都存在这个情况,很不解,手册里也没提到太多关于4位驱动注意事项...
Delay1ms(15);
lcd_wcmd(0x02);
这是LCD初始化部分加了02指令后的完整部分:
//Cepark51实验板LCD1602显示程序
//日期:2008年8月20日 四位控制版本
//文件名:lcd1602_c.c
//作者:yanwuxu
#include "at89x51.h"
#define uchar unsigned char
#define uint unsigned int
#define lcd_bus P0 //lcd1602 数据总线
sbit lcd_rs=P1^0; //lcd1602 数据/命令选择端,1数据,0指令
sbit lcd_rw=P1^1; //lcd1602 读写控制端,1读,0写
sbit lcd_en=P1^2; //lcd1602 使能端,高脉冲有效
void Delay1ms(uint mDelay1) //1ms延时
{
uint mDelay2;
for(;mDelay1>0;mDelay1--)
{ for(mDelay2=0;mDelay2<114;mDelay2++)
{;}
}
}
void lcd_wdata(uchar lcd_data) //lcd1602写数据
{
lcd_bus=lcd_data; //先送高4位
lcd_rs=1;
lcd_rw=0;
lcd_en=0;
Delay1ms(3);
lcd_en=1;
// Delay1ms(1);
lcd_bus=(lcd_data<<=4); //再送低四位
lcd_rs=1;
lcd_rw=0;
lcd_en=0;
Delay1ms(3);
lcd_en=1;
}
void lcd_wcmd(uchar lcd_cmd) //lcd写指令
{
lcd_bus=lcd_cmd;
lcd_rs=0;
lcd_rw=0;
lcd_en=0;
Delay1ms(3);
lcd_en=1;
// Delay1ms(1);
lcd_bus=(lcd_cmd<<=4);
lcd_rs=0;
lcd_rw=0;
lcd_en=0;
Delay1ms(3);
lcd_en=1;
}
void lcd_disp_byte(uchar x,uchar y,uchar lcd_dat) //lcd写字符,x横位置1-16,y行,y为1为显示在第一行,其它的为显示在第2行
{
uchar lcd_address;
if(y==1)
lcd_address=0x80+x-1; //从1-16
else
lcd_address=0xc0+x-1; //从1-16
lcd_wcmd(lcd_address);
lcd_wdata(lcd_dat);
}
void lcd_disp_str(uchar x,uchar y,uchar code *s) //lcd写字符串,x横位置1-16,y行,y为1为显示在第一行,其它的为显示在第2行
{
uchar lcd_address;
if(y==1)
lcd_address=0x80+x-1; //从1-16
else
lcd_address=0xc0+x-1; //从1-16
lcd_wcmd(lcd_address);
while(*s>0)
{
lcd_wdata(*s);
s++;
};
}
void lcd_init() //lcd初始化
{
Delay1ms(20);
lcd_wcmd(0x02);
Delay1ms(15); //延时15ms
lcd_wcmd(0x28); //
Delay1ms(15);
lcd_wcmd(0x28);
Delay1ms(15);
lcd_wcmd(0x28);
lcd_wcmd(0x0c);
lcd_wcmd(0x06);
lcd_wcmd(0x01);
}
void main()
{
lcd_init();
while(1)
{
lcd_disp_byte(3,1,'K'); //测试
lcd_disp_str(4,2,"123456");
}
}
用户1400793 2008-8-24 16:54