1. 程式人生 > >基於51微控制器的LCD1602顯示

基於51微控制器的LCD1602顯示

最近工作簽了,沒啥事,畢業設計題目也沒出來,打算重新學一下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 ^_^ 。