#include<reg51.h>
#include<intrins.h>
#include<absacc.h>
#define uchar unsigned char
#define uint unsigned int
#define D_port P0 //设置端口
code char table[]="go for a better tomorrow"; //将要显示的设置成一个数组
sbit RS=P2^0;//很奇怪,我把这个定义到P3口就不行,死也出不来,只能定义到2口,可能我那个3口坏了
sbit RW=P2^1;
sbit EN=P2^2;
void delay(uint t) //单位延时1ms,总延时1ms*t.(121为实验测试值)
{ //这个延时函数很有名的,郭天祥的,我都用这个
uint i,j;
for(i=0;i<t;i++)
for(j=0;j<121;j++);
}
void check_busy()//由于液晶显示没有单片机运行速度那么快,因此每次都要检查它是不是把上个命令执
{ //行完
D_port=0xff;
RS=0;
RW=1;
EN=1;
_nop_();
while(D_port&0x80);//如果最高位是1的话,那么就一直运行分号,就是空语句,一直到最高位为0,即为
EN=0; //空闲
}
void lcdwritecom(uchar cmd)//液晶显示是不需要读程序的,只需要写程序,你把东西写进去后,它自动
{ //读的,而写的过程分为两个,一个是将命令写进去,液晶工作,如何工作
check_busy(); //是移动的还是直接显示,这些都是需要命令的,而且把显示器清空也是需
RS=0; //要命令的。而还有一个就是数据写入,数据写入和命令写入只有一个rs不
RW=0; //同,其他的都差不多,命令写入就是写入你要的数据啊,字符啊什么的
EN=0;
D_port=cmd;
_nop_();
EN=1; //这部分是字符写入的程序
delay(10);
EN=0;
_nop_();
RS=1;
RW=1;
}
void lcdwritedate(uchar date)//数据写入,仔细研究时序图
{
check_busy();
RS=1;
RW=0;
EN=0;
D_port=date;
_nop_();
EN=1;
delay(10);
EN=0;
_nop_();
RS=0;
RW=1;
}
void init() //严格按照datesheet上执行语句
{
delay(20);
lcdwritecom(0x38);
delay(10);
lcdwritecom(0x38);
delay(10);
lcdwritecom(0x38);
check_busy();
lcdwritecom(0x38);
check_busy();
lcdwritecom(0x08);
check_busy();
lcdwritecom(0x01);
check_busy();
lcdwritecom(0x06);
check_busy();
lcdwritecom(0x0c);
delay(5);
}
void setpost(uchar postx,uchar posty) //这部分代码是研究你的光标的位置,x是横坐标,y是纵坐标
{ //y只有两行,x有16个范围,里面的代码就是;如果x是第二行
posty=posty&0x1; //的话,那么y的坐标就要加1.
if(posty)postx|=0x40;
post|=0x80;
lcdwritecom(post); //最后将确定的总的坐标给写进去
}
void displaychar(uchar x,uchar y,uchar a)//其实液晶是一个一个显示出来的,所以要写一个单个字节
{ //的显示函数,先查忙不忙,再确定位置,后来,将数字写
check_busy(); //进去
setpost(x,y);
lcdwritedate(a);
}
void displaystring(uchar x,uchar y,uchar code *ptr)//显示全部的数字,这里就要用到字符储存特性
{
uchar length=0,num=0;
check_busy();
while(ptr[length]!='\0') //这就是字符在数组里的储存的最后一个标志符
{
displaychar(x,y,ptr[length]);//其实这部分也可以用for 来实现,但是一般情况下来说,for都是知道
x++; //了有几个数之后才用的,而while是不知道有几个数的
length++;
if(x==0x20) //这部分是由于你的数组有很多,你想分开两部分显示,你想在什么地方
{ //重新开始,就在这里设置
x=0x10; //由于你重新设置了一个新的地方,这个x的值是坐标,不是x的地址,不
y^=1; //是那种0x80+的那种,而是你从最左边开始数,第几个
}
delay(20);
}
for(num=0;num<32;num++) // 从这个for 开始,代表的意思就是说要移动了,lcdwritecom(0x18)在
{ // datesheet 上表示的意思就是左移,右移是lcdwritecom(0x1c)
lcdwritecom(0x18);
delay(200);
}
for(num=0;num<32;num++)//这部分就是又移
{
lcdwritecom(0x1c);
delay(200);
}
}
void main()
{
init();
while(1)
{
displaystring(0x10,0,table);
}
}
整体实现:有一组字符从左边移到右边,直到消失,再从左边移到右边如此循环
值得注意的地方:接口一定要接对,时序也要正确,时间的延迟5或者10毫秒差不多