最近工作签了,没啥事,毕业设计题目也没出来,打算重新学一下51单片机,补补功课。今天看着 LCD1602 的
datasheet试着自己编写,proteus仿真软件没有LCD1602,使用LM016来代替,先了解一下LCD1602的各引脚
功能。如下图:
图1 LCD1602 引脚图
51单片机编程要使用RS、E和D0-D7引脚,由于R/W为对1602读写的引脚,不需要对其进行读,所以接低电平。
然后根据下图的LCD1602时序图写指令和数据。
图2 LCD1602时序图
先写两个函数,写指令和数据(第一次,我注释了“EN=1”后面的延时):
write_com(uchar com) //写指令
{
EN=0;
RS=0;
P0=com;
delayms(1);
EN=1;
delayms(1);
EN=0;
}
write_data(uchar dat) //写数据
{
EN=0;
RS=1;
P0=dat;
delayms(1);
EN=1;
delayms(1);
EN=0;
}
程序如下:
#include <reg51.h>
#include <stdio.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS=P3^0; //液晶数据指令选择端
sbit EN=P3^1; //液晶使能端
sbit led=P2^2;
uchar code table[]="Dear Chenli ,";
uchar code table1[]="I LOVE YOU !";
void delayms(uint a) //延时毫秒
{
uint x,y;
for(x=a;x>0;x--)
for(y=110;y>0;y--);
}
write_com(uchar com)//写指令
{
EN=0;
RS=0;
P0=com;
delayms(1);
EN=1;
//delayms(1);
EN=0;
}
write_data(uchar dat)//写数据
{
EN=0;
RS=1;
P0=dat;
delayms(1);
EN=1;
//delayms(1);
EN=0;
}
void init()
{
write_com(0x38);//设置16x2显示,5X7点阵,8位数据接口,
write_com(0x0c);//设置开显示,不显示光标
write_com(0x06);//写一个字符后,地址指针加1
write_com(0x01);//显示清0,数据指针清0
}
void main(void)
{
uchar i;
init();
write_com(0x80);//+0x10
for(i=0;i<strlen(table);i++)
{
write_data(table[i]);
delayms(5);
}
write_com(0x80+0x40);
for(i=0;i<strlen(table1);i++)
{
write_data(table1[i]);
delayms(1);
}
/*
for(i=0;i<16;i++) //移屏操作,16次,把屏幕右边的内容移到显示区域内
{
write_com(0x18);//移屏指令
delayms(100);
}
*/
while (1)
{
led=0;
delayms(500);
led=1;
delayms(500);
}
}
得到的显示结果如下:
说明仿真结果是正确的。
对上面的程序稍加修改,LCD1602第一行起始地址为0x80+0x10第二行起始地址为0x80+0x40+0x10,由于,仍不
加延时,但是当我想实现以下LCD1602的移屏效果,却得不到想要的结果,如下:
上图的代码如下:
#include <reg51.h>
#include <stdio.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS=P3^0; //液晶数据指令选择端
sbit EN=P3^1; //液晶使能端
sbit led=P2^2;
uchar code table[]="Dear Chenli ,";
uchar code table1[]="I LOVE YOU !";
void delayms(uint a) //延时毫秒
{
uint x,y;
for(x=a;x>0;x--)
for(y=110;y>0;y--);
}
write_com(uchar com)//写指令
{
EN=0;
RS=0;
P0=com;
delayms(1);
EN=1;
//delayms(1);
EN=0;
}
write_data(uchar dat)//写数据
{
EN=0;
RS=1;
P0=dat;
delayms(1);
EN=1;
//delayms(1);
EN=0;
}
void init()
{
write_com(0x38);//设置16x2显示,5X7点阵,8位数据接口,
write_com(0x0c);//设置开显示,不显示光标
write_com(0x06);//写一个字符后,地址指针加1
write_com(0x01);//显示清0,数据指针清0
}
void main(void)
{
uchar i;
init();
write_com(0x80+0x10);//+0x10 第一次修改处,地址由0x80变为0x80+0x10
for(i=0;i<strlen(table);i++)
{
write_data(table[i]);
delayms(5);
}
write_com(0x80+0x40+0x10); //第一次修改处,地址由0x80+0x40变为0x80+0x40+0x10
for(i=0;i<strlen(table1);i++)//第一次修改,取消移屏的注释
{
write_data(table1[i]);
delayms(1);
}
for(i=0;i<16;i++) //移屏操作,16次,把屏幕右边的内容移到显示区域内
{
write_com(0x18); //移屏指令
delayms(100);
}
while (1)
{
led=0;
delayms(500);
led=1;
delayms(500);
}
}
仔细观察,发现第一行的内容不见了,仿真时发现第一行的显示在0x80~(0x80+0x0F)区域,但是程序是写在
(0x80+0x10)~(0x80+0x1F),我检查了几遍,还是不对,百思不得其解。
最后我修改了一下对1602写数据、指令的延时后(取消程序中延时函数的注释),效果一下就出来了。如下:
由于是图片,所以效果不是很好,仿真时可以看到整个移屏的效果,还不错。
这是为什么呢?为什么添加了延时,显示就正确了?
可能是数据还没有完全写完,所以。。。。。
OVER ^_^ 。