LCD1602液晶显示汉字

使用LCD1602 显示字符会比使用七段数码管方便 可显示内容也多的多  1602内部的字符发生器 CGROM中已经存储了160多个字符 ,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是“01000001B,显示时把41H的点阵字符显示出来,就可以看到字符“A”。
常用的方法是 写完数据显示地址后 直接写入字符串 “A”,其实直接写入0x41也可以显示“A”;
1602中有这样几个区:
CGRAM 区为用户自定义字符区  
DDRAM 为字符显示地址(位置)数据存贮器
CGROM为 液晶模块内部字符发生存储器
使用1602显示汉字 就需要是用到 CGRAM,需要将取模后的点阵字符写入CGRAM ,以备后面读出显示。
1602 使用的显示点阵大小是 58 ,可以使用取模软件获得文字的点阵显示字符,但是点阵大小最小为88, 要取得5*8的字模 只需要空出前三列即可。
字模提取.png
将生成的点阵数组保存到CGRAM存储器中,生成自定义字符。1602内部CGRAM用于自定义的字符点阵的存储,总共64字节。由上一步点阵提取可知,每一个字符由8个字节数据组成。所以64字节CGRAM存储器,能够存储8组自定义字符的点阵数组。
按照CGRAM地址划分为 0-7为第一组,8-15为第二组,依次类推56-63为第8组数据。
把自定义字符的数组按8个字节一组存储到CGRAM中。
自定义字符存储到CGRAM的任意一组以后,每一个组(8个字节)也有一个显示编码。按顺序依次为00H-07H 。显示时,只要调用每一组的编码,即可以显示相应的字符。
注:内部常用字符显示时,显示编码是从0x20开始的。0x00-0x0f是专门留给自定义字符显示的。0x00-0x07和0x08-0x0f内容是一样的。例如:调用0x01 位置和0x09位置,显示的内容是一样的。
1602显示”你好”:
IMG_20120425_154514.jpg
51单片机的默认是将变量定义在直接寻址data区,这个区域是片内RAM的低128字节,所以存储的空间有限,所以编程时可以把一些变量编译在 间接寻址的idata区(52是80H~0FFH区域)或者 64 程序存储器 code 区中。
LCD1602显示程序代码:
    #include <reg52.h>
#include “lcd1602.h”

#define uchar unsigned char // 宏定义uchar 为无符号字符
#define uint unsigned int

uchar idata words[4][8] = {
{ 0x01,0x02,0x06,0x02,0x02,0x02,0x02,0x00}, //你字左边
{ 0x08,0x0F,0x15,0x04,0x15,0x15,0x04,0x0C}, //你字右边
{ 0x00,0x04,0x1F,0x0A,0x04,0x0A,0x00,0x00}, //好字左边
{ 0x1E,0x02,0x04,0x1F,0x04,0x04,0x0C,0x00} //好字右边
};

void main()
{
uchar i;

LCD_Init();

for(i=0;i<4;i++)
{
LCD_CGRAM_WriteByte(words[i],i);
LCD_WriteByte(0x80+i,0);
LCD_WriteByte(i,1);
}

LCD_WriteString(“Wrold !!”,2);

/**这样也可以显示“A”

LCD_WriteByte(0xCA,0);
LCD_WriteByte(0x41,1);

*/
while(1);

}
lcd1602.h :
    #define uchar unsigned  char     // 宏定义uchar 为无符号字符
#define uint unsigned int

#define DataPin P0

sbit LCD_RS = P2^4; // LCD 数据/ 命令选择 ,高电平时选择数据寄存器
sbit LCD_RW = P2^5; // LCD 读 / 写选择 ,高电平时读操作
sbit LCD_E = P2^6; // LCD 使能
sbit IR_DQ = P2^3; // 红外接收头数据线

void LCD_BusyCheck(void);
void LCD_WriteByte(uchar var,bit RS);
void LCD_Init(void);
void LCD_WriteString(uchar str,uchar line);
void LCD_CGRAM_WriteByte(uchar
p,uchar num);
void LCD_Delay(uint n);

void LCD_Delay(uint n)
{
while(–n); // 8us一次
}

void LCD_BusyCheck(void)
{
uchar isBusy;

LCD_RS = 0;
LCD_RW = 1;

LCD_E = 1;
LCD_Delay(10);
isBusy = DataPin & 0x80;
LCD_E = 0;

if(isBusy == 0x80)
{
LCD_BusyCheck();
}
}

void LCD_WriteByte(uchar var,bit RS ) //参数 RS为 LCD数据/ 命令选择 ,高电平时选择数据寄存器
{
LCD_BusyCheck();

LCD_RS = RS;
LCD_RW = 0;
DataPin = var;

LCD_E = 0;
LCD_Delay(70); //必须延时500us左右
LCD_E = 1;
LCD_Delay(5);
LCD_E = 0;

}

void LCD_WriteString(uchar str,uchar line)
{
uchar i = 0,addr;

if(line == 1) { addr = 0x80;}
if(line == 2) { addr = 0xC0;}

while(1)
{
LCD_WriteByte(addr+i,0); //写入地址
LCD_WriteByte(str[i],1);
i++;
if(i==16 || str[i] == ‘\0’){ break;}
}
}

void LCD_CGRAM_WriteByte(uchar
p,uchar num) //将自定义字符写入CGRAM中,最多64字节,uchar num为自定义字符存放位置 0-7
{
uchar i,place;

place = 0x40 + 8(num&0x07); // num&0x07 保证num取值范围为 0-7

for(i=0;i<8;i++)
{
LCD_WriteByte(place+i,0);
LCD_WriteByte(p[i],1);
}
}

void LCD_Init(void)
{
LCD_Delay(1875); //延时15ms

LCD_WriteByte(0x38,0);

LCD_Delay(625); //延时5ms

LCD_WriteByte(0x38,0); //配置LCD为4位数据总线,双行显示,5
7点阵字符

LCD_WriteByte(0x08,0); //配置LCD关闭显示,无光标,无闪烁

LCD_WriteByte(0x01,0); //LCD清屏

LCD_WriteByte(0x06,0); //LCD光标右移

LCD_WriteByte(0x0C,0); //打开LCD显示

}