一、LCD简介
LCD作为一种常见的外设,是广泛应用在单片机外围电路的一种显示设备。LCD1602和LCD12864是典型的单片机显示电路中常用的模块,两种该模块都属于点阵式液晶显示模块。

1、LCD1602模块
1602液晶也叫160字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵型液晶模块。1602LCD是指显示内容为16*2,显示两行,每行可以显示16个字符液晶模块。液晶1602引脚说明如下表中所示:

对LCD1602有两种操作方式,即“读”和“写”。“读”操作就是读液晶是否处于“忙”状态,如果是,就等液晶“空闲”时再往液晶“写”(写指令或数据)。一般情况下对于LCD1602可以不用“读”操作,用一个短暂延时即可。液晶1602工作之前,要对1602进行一些设置。

Function set功能设置
1602模块的功能设置指令码如下表中所示:

设置模块数据接口的宽度和1602显示屏的显示方式,即单片机1602模块接口数据总线4位或8位、LCD显示行数和显示字符点阵的规格。DL:数据接口宽度标志。DL=1,8位数据DB7~DB0;DL=0,四位数据总线DB7~DB4;DB3~DB0不用,使用此方式传送数据,需分两次进行。N:显示行数标志。N=1,双行显示;N=0,单行显示方式。F:现实点阵字符字体标志。F=1,5*10点阵+光标显示;F=0:5*7点阵+光标显示方式。

Display on/off control(显示开/关控制)
1602模块的指令代码如下表所示:

D:显示开/关标志。D=1,开显示;D=0,关显示。
C:光标显示控制标志。C=1,光标显示;C=0,光标不显示。
B:闪烁控制标志。B=1,光标所指位置上,交替显示全黑点阵和显示字符,产生闪烁效果,f=250KHZ时,闪烁频率为0.4ms左右,通过设置,光标可以与其所指位置的字符一起闪烁。

Entry mode set(设置输入方式)

N=1,当读和写一个字符后地址指针加1,且光标加1;N=0,当读和写一个字符后地址指针减1,且光标减1.

S=1,当写一个字符时,整屏显示左移(N=1)或右移(N=0)。S=0,当写一个字符时,整屏显示不移动。

  1. Clear display(清屏)

  1. 所谓清屏就是把数据指针清零和所有显示清零

2、12864模块

12864是128*64点阵液晶模块的点阵数简称,其引脚说明如下表中所示:

对于液晶12864同1602也有两种工作方式,“读”和“写”。“读”操作即判断液晶是否处于“忙”状态,一般对12864用一个短延时即可。

  1. Function set 功能设置
     

  1. DL:数据接口宽度标志。DL=1(必须是1),8位数据DB7~DB0。
    RE=1,扩充指令集动作;RE=0,基本指令集动作。
    RS和R/W均为低电平的情况下,是“写指令”。

  2. Display on/off control(显示开/关控制)

  1. D:显示开/关标志。D=1,开显示;D=0,关显示。
    C:光标显示控制标志。C=1,光标显示;C=0,光标不显示。
    B:光标位置反白开关控制位。B=1,光标位置反白ON(将光标所在处的资料反白显示);B=0,光标位置反白OFF。

  2. Clear display(清屏)

同1602,清屏就是把数据指针清零和所有显示清零。

12864串行显示
串行工作模式下:
CS(RS):片选信号线,进行数据操作时必须将CS端拉高。
SCLK(R/W):串行同步时钟,每操作一位数据都要有一个SCLK跳变沿,上升沿有效,当SCLK由低电平变为高电平的瞬间,液晶将SID上的数据读入或输出。
SID(EN):串行数据,每一次操作都由三个字符组成,第一个字节向控制器发送命令控制字,若为写指令则发送1111 1000,若为写数据则发送1111 1010。第二个字节高四位发送指令或数据的高四位,第二个字节低四位补0。第三个字节低四位发送指令或数据的低四位,第三个字节的低四位补0。

汉字显示LCD12864显示汉字,只能显示4行,每行显示8个汉字或16个字符。汉字的地址分布如下: LCD12864显示汉字,只能显示4行,每行显示8个汉字或16个字符。汉字的地址分布如下:

二、电路设计

以12864显示模块的电路为例。

1、并行显示电路

2、串行显示电路

三、程序设计

1、1602显示单个数字

#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit Lcd1602_EN=P2^5; //使能端
sbit Lcd1602_RS=P1^0; //数据命令选择端
sbit Lcd1602_RW=P1^1; //读写选择端,可以直接电路置地,只使用写功能
void delay(uint i)
{
	uint x,y;
	for(x=i;x>0;x--)
		for(y=110;y>0;y--);
}
 
void write_com(uchar com)
{	
	Lcd1602_RS=0;//命令
	Lcd1602_RW=0;//写
	Lcd1602_EN=0;
	P0=com; 
	delay(5);
	Lcd1602_EN=1;
	delay(5);
	Lcd1602_EN=0;
}
void write_data(uchar dat)
{
	Lcd1602_RS=1;
	Lcd1602_RW=0;
	Lcd1602_EN=0;
	P0=dat;
	delay(5);
	Lcd1602_EN=1;
	delay(5);
	Lcd1602_EN=0;
}
void Lcd_Init()
{	
	write_com(0x38);//16*2显示,8位数据接口
	write_com(0x0c);//显示器开,光标开,光标闪烁
	write_com(0x06);//显示字符不动,光标右移
	write_com(0x01);//清屏
}
void display(uchar c,int v)//显示一个三位的数字
{
	uint shu;
	write_com(c);
  	
   	write_com(0x80);//设置第一行第一列写
   	shu=v/100;
   	write_data(shu+'0');
 
   	shu=v%100/10;
   	write_data(shu+'0');
 
  	shu=v%10;
   	write_data(shu+'0');
 
} 
void main()
{
	int v;
	v=789;
	Lcd_Init();
	while(1)
	{
		display(0x80,v);
	}
}

2、1602显示单个字符

#include <reg52.h>
#include "LCD1602.h"
uchar table[]={"www.baidu.com"};
uchar num;
void display(int v)
{
   	int shu;
   	write_com(0x80);
   	for(num=0;num<13;num++)
   	{
   		write_data(table[num]);
		delay(5);
   	}
   	write_com(0x80+40);
   	shu=v/100;
   	write_data(shu+'0');
   	shu=v%100/10;
   	write_data(shu+'0');
	shu=v%10;
   	write_data(shu+'0');
	write_data(0xdf);
	write_data('C');
	delay(5);
}
void main()
{
	uint v;
	Lcd_Init();
	
	while(1)
	{
		v=100;
		display(v);
	}
}
 
//lcd1602.h文件
#ifndef _LCD1602_
#define _LCD1602_
#define uchar unsigned char
#define uint unsigned int
sbit Lcd1602_EN=P2^5; //ʹÄܶË
sbit Lcd1602_RS=P1^0; //Êý¾ÝÃüÁîÑ¡Ôñ¶Ë
sbit Lcd1602_RW=P1^1; //¶ÁдѡÔñ¶Ë,¿ÉÒÔÖ±½Óµç·Öõأ¬Ö»Ê¹ÓÃд¹¦ÄÜ
	void delay(uint i)
	{
		uint x,y;
		for(x=i;x>0;x--)
			for(y=110;y>0;y--);
	}
	void write_com(uchar com)
	{	
		Lcd1602_RS=0;//ÃüÁî
		Lcd1602_RW=0;//д
		Lcd1602_EN=0;
		P0=com; 
		delay(5);
		Lcd1602_EN=1;
		delay(5);
		Lcd1602_EN=0;
	}
	void write_data(uchar dat)
	{
		Lcd1602_RS=1;
		Lcd1602_RW=0;
		Lcd1602_EN=0;
		P0=dat;
		delay(5);
		Lcd1602_EN=1;
		delay(5);
		Lcd1602_EN=0;
	}
	void Lcd_Init()
	{	
		write_com(0x38);//16*2ÏÔʾ£¬8λÊý¾Ý½Ó¿Ú
		write_com(0x0c);//ÏÔʾÆ÷¿ª£¬¹â±ê¿ª£¬¹â±êÉÁ˸
		write_com(0x06);//ÏÔʾ×Ö·û²»¶¯£¬¹â±êÓÒÒÆ
		write_com(0x01);//ÇåÆÁ
	}
 
#endif

3、12864显示汉字

#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit RS=P1^0;
sbit RW=P1^1;
sbit EN=P2^5;
sbit PSB=P1^2;
uchar code table1[]={"人生若只如初见,"};
uchar code table2[]={"何事秋风悲画扇。"};
uchar code table3[]={"等闲变却故人心,"};
uchar code table4[]={"却道故人心易变。"};
void delay(uint i)
{
	uint x,y;
	for(x=i;x>0;x--)
		for(y=110;y>0;y--);
}
void write12864_cmd(uchar cmd)
{
	RS=0;
	RW=0;
	EN=0;
	P0=cmd;
	delay(5);
	EN=1;
	delay(5);
	EN=0;
}
void write12864_data(uchar dat)
{
	RS=1;
	RW=0;
	EN=0;
	P0=dat;
	delay(1);
	EN=1;
	delay(1);
	EN=0;
}
void lcd12864_init()
{
	PSB=1;
	write12864_cmd(0x30);//设置数据宽度为8位
	delay(5);
	write12864_cmd(0x0c);//开显示
	delay(5);
	write12864_cmd(0x01);//清屏
	delay(5);
}
void lcd_pos(uchar x,uchar y)//显示位置坐标
{
	uchar pos;
	if(x==0)
	{x=0x80;}
	else if(x==1)
	{x=0x90;}
	else if(x==2)
	{x=0x88;}
	else if(x==3)
	{x=0x98;}
	pos=x+y;
	write12864_cmd(pos);
}
void main()
{
	lcd12864_init();
	while(1)
	{
		uchar i;
		lcd_pos(0,0);
		for(i=0;i<16;i++)
		{
		 	write12864_data(table1[i]);
		}
		lcd_pos(1,0);
		for(i=0;i<16;i++)
		{
		 	write12864_data(table2[i]);
		}
		lcd_pos(2,0);
		for(i=0;i<16;i++)
		{
		 	write12864_data(table3[i]);
		}
		lcd_pos(3,0);
		for(i=0;i<16;i++)
		{
		 	write12864_data(table4[i]);
		}
	}
}

4、12864串行显示程序

#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit CS=P1^0;
sbit SCLK=P1^1;
sbit SID=P2^5;
sbit PSB=P1^2;
uchar code table1[]={"人生若只如初见,"};
uchar code table2[]={"何事秋风悲画扇。"};
uchar code table3[]={"等闲变却故人心,"};
uchar code table4[]={"却道故人心易变。"};
void delay(uint i)
{
	uint x,y;
	for(x=i;x>0;x--)
		for(y=110;y>0;y--);
}
void sendbyte(uchar zdata)//根据液晶串口通信协议,发送数据
{
	uint i;
	for(i=0;i<8;i++)
	{
		if((zdata<<i)&0x80)
		{
			SID=1;
		}
		else
		{
			SID=0;
		}
		SCLK=0;
		SCLK=1;
	} 	
}
void write12864_com(uchar cmdcode)
{
	CS=1;
	sendbyte(0xf8);//写指令
	sendbyte(cmdcode&0xf0);//指令高四位
	sendbyte((cmdcode<<4)&0xf0);//低四位
	delay(1);
}
void write12864_data(uchar dispdata)
{
	CS=1;
	sendbyte(0xfa);//写数据
	sendbyte(dispdata&0xf0);//数据高四位
	sendbyte((dispdata<<4)&0xf0);//低四位
	delay(1);
}
void lcd12864_init()
{
	PSB=0;
	write12864_com(0x30);
	delay(5);
	write12864_com(0x0c);
	delay(5);
	write12864_com(0x01);
	delay(5);
}
void lcd_pos(uchar x,uchar y)//显示位置坐标
{
	uchar pos;
	if(x==0)
	{x=0x80;}
	else if(x==1)
	{x=0x90;}
	else if(x==2)
	{x=0x88;}
	else if(x==3)
	{x=0x98;}
	pos=x+y;
	write12864_com(pos);
}
void display(uchar *s)
{
	while(*s>0)
	{
		write12864_data(*s);
		s++;
		delay(1);
	}
}
void main()
{
	
	lcd12864_init();
	while(1)
	{ 
	   lcd_pos(0,0);
	   display(table1);
	   lcd_pos(1,0);
	   display(table2);
	   lcd_pos(2,0);
	   display(table3);
	   lcd_pos(3,0);
	   display(table4);
	}
}