lcd1602能否顯示漢字
1602液晶是字符型液晶,總共有2行,每行16個(gè)字符。每個(gè)字符有效的可顯示字體是5*8點(diǎn)陣字體。所以通常無(wú)法顯示中文。中文的顯示必須選擇圖形點(diǎn)陣型液晶。
特別地:是指,顯示“年月日”,之類的簡(jiǎn)單的漢字吧?最多支持8個(gè)CGRAM字符??梢宰约鹤?。調(diào)用字模代碼0-7。如:“年”的CGRAM單元數(shù)據(jù)為:0FH,09H,0FH,09H,0FH,09H,13H,00H。這8個(gè)字節(jié)寫入CGRAM單元00H-07H。調(diào)用字符代碼0??梢钥吹街形摹澳辍?。
lcd1602顯示漢字的概念
首先:我們要弄清楚一個(gè)概念,其實(shí)我們使用1602顯示中文漢字,就是利用其內(nèi)部的自定義字節(jié)空間。
第一行的內(nèi)容對(duì)應(yīng)DDRAM中80H到8FH內(nèi)容 第二行的內(nèi)容對(duì)應(yīng)DDRAM中C0H到CFH內(nèi)容
通過(guò)查看LCD1602的用戶手冊(cè),里面提到當(dāng)我們需要想CGRAM寫入數(shù)據(jù)時(shí),我們需要先寫入CGRAM的地址,從手冊(cè)上可知,CGRAM的地址為0x40.所以當(dāng)我們要寫入數(shù)據(jù)時(shí),要先寫入一條地址命令 write_com(0x040);
然后把你要寫入的數(shù)據(jù)通過(guò)寫數(shù)據(jù)命令寫入 write_date( 你要寫得數(shù)據(jù));
把你要顯示漢字的代碼存放在CGRAM里,就相當(dāng)于其他常用字符一樣固定在LCD里面了,把你要顯示漢字的代碼存放在CGRAM里,就相當(dāng)于其他常用字符一樣固定在LCD里面了,就相當(dāng)于把你要顯示漢字的代碼存放在CGRAM里,就相當(dāng)于其他常用字符一樣固定在LCD里面了,我們都知道LCD1602內(nèi)部有一個(gè)64字節(jié)的自定義CGRAM,那么好,我們就是要利用自定義字節(jié)來(lái)達(dá)到顯示漢字的效果。
我們知道一個(gè)字符占8個(gè)字節(jié),所以在CGRAM能夠存放8個(gè)字符。 也就是說(shuō),這個(gè)64字節(jié)的CGRAM是給我們提供寫入數(shù)據(jù)的, 那么我們?cè)趺窗盐覀円臐h字寫入CGRAM呢?
DDRAM顯示用ram,直接和屏幕上的點(diǎn)相對(duì)應(yīng)。屏幕上的一個(gè)點(diǎn)和ddram中的一個(gè)位對(duì)應(yīng),字符屏的ddram和圖形屏的ddram有一點(diǎn)點(diǎn)區(qū)別。
CGROM 中存儲(chǔ)了一些標(biāo)準(zhǔn)的 字符的字模編碼,是液晶屏出廠時(shí)固化在控制芯片中的,用戶不能改變其中的存儲(chǔ)內(nèi)容,只能讀取調(diào)用,包含有標(biāo)準(zhǔn)的ASCII碼、日文字符和希臘文字符。
CGRAM 是控制芯片留給用戶,用以存儲(chǔ)用戶自己設(shè)計(jì)的字模編碼。
字模編碼都要先被讀取到對(duì)應(yīng)的DDRAM中,經(jīng)中轉(zhuǎn)以后,屏幕的相應(yīng)位置才顯示出字符。對(duì)于字符屏,要顯示某個(gè)字符時(shí),往ddram里寫字符的索引(一般都是ascii碼)就可以完成顯示。
lcd1602顯示漢字的程序
漢字的字模:
就是顯示出來(lái)的漢子字體結(jié)構(gòu)。
要定義字模就需要知道1602的CG RAM地址和顯示字符的地址 DD RAM :
1 ? ?2 ? ?3? ?4? ?5 ? ?6? ?7? ?8? ?9? 10 11 ?12 13?14 ?15 16
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
第一行第一個(gè)字符的地址是( 0x80) ,后面的字符地址以此類推
第二行第一個(gè)字符的地址為 ( 0x80 + 0x40),需要在第一行的基地址后面加上一個(gè)偏移 量0x40,后面的地址在此基址上再依次加一。
void delay(unsigned int time_i)
{
int i;
for (;tim》0;tim--)
? {
for (i=0;i《10;i++);
? }
}
void command_out (char out_data)
{
RW=0;
RS=0;
EN=1;
DB=out_data;
EN=0;
delay(10);
}
void OUTD(char out_data)
{
RS=1;
RW=0;
EN=1;
DB= out_data;
EN=0;
delay(10);
}
OUTI()是寫入指令的函數(shù), OUTD()是寫入數(shù)據(jù)的函數(shù)。 如:
左上角第一個(gè)5*7的顯示數(shù)據(jù)為:
0x00,0x01,0x81,0x12,0x24,0x41,0x81,0x10 藍(lán)色區(qū)域的相應(yīng)位為1
這樣就可以寫出全部4個(gè)5*7點(diǎn)陣的顯示數(shù)據(jù)了,把它封裝在一個(gè)數(shù)組中,如數(shù)組,
hanzi[]={0x00,0x01,0x81,0x12,0x24,0x41,0x81,0x10, …… …… …… }
之后利用命令:
OUTI(0X40);
for (i=0;i《64;i++)
{
OUTD(neu[i]);
}
將這個(gè)數(shù)組中的數(shù)據(jù)賦值到1602內(nèi)部CGRAM中。完成后,再設(shè)置數(shù)據(jù)在1602上的 顯示地址,根據(jù)圖1的結(jié)構(gòu),設(shè)置好位置,如在第一行第一個(gè)字符和第二個(gè)字符以及第二行
第一個(gè)字符和第二個(gè)字符處顯示:
Command_out (0x80+0x00);
for (i=0;i《4;i++)
{
data_out (i);
}
Command_out(0x80+0x40);
for (i=4;i《8;i++)
{ data_out(i);
}
command_out()的作用是設(shè)置顯示的起始地址,data_out()的作用是將hanzi[]數(shù)組中的16 進(jìn)制數(shù)據(jù)發(fā)送出去,每一個(gè)16進(jìn)制數(shù)字對(duì)應(yīng)之5*7點(diǎn)陣上的每一行內(nèi)容。第1行第1個(gè)字 符需要8個(gè)16進(jìn)制數(shù)據(jù),第1行第2個(gè)字符處也需要816進(jìn)制數(shù)據(jù)。還有第2行的兩個(gè)字 符點(diǎn)陣,這樣顯示一個(gè)漢字需要32個(gè)16進(jìn)制數(shù)據(jù)。
下面列舉一個(gè)實(shí)例(proteus仿真通過(guò))
//*************************************************************************************** //
硬件連接:1602VDD接5V,VO接地,BL1接5V,BL2接地,8根數(shù)據(jù)線接P0口,RS RW E分別接P2.0、P2.1、P.4口
//***************************************************************************************//
#include 《reg52.h》
#include 《string.h》
#define Busy 0x80 //用于檢測(cè)LCM狀態(tài)字中的Busy標(biāo)識(shí)
#define LCM_Data P0 ;
sbit LCM_RS=P2^0; //寄存器選擇
sbit LCM_RW=P2^1; //讀/寫控制
sbit LCM_E=P2^4; //讀/寫使能
int i,j;
//自定義字符列表 //
=====================================================================================
unsigned char character0[8] = {0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02}, //年
character1[8] = {0x0f,0x09,0x0f,0x09,0x0f,0x09,0x0b,0x11}, //月
character2[8] = {0x0f,0x09,0x09,0x09,0x0f,0x09,0x09,0x0f}, //日
characterN[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //日
//==========================================================
//=========================================================
//延時(shí)程序
//=======================================================
void Delay5Ms(void)
{
unsigned long int TempCyc = 5552;
while(TempCyc--);
}
void Delay400Ms(void)
{
unsigned char TempCycA = 5;
unsigned int TempCycB;
while(TempCycA--)
? {
TempCycB=7269;
while(TempCycB--);
? };
}
//===================================================================
//讀寫子程序
//=================================================================
//讀數(shù)據(jù)
unsigned char ReadDataLCM(void)
{
LCM_RS = 1;
LCM_RW = 1;
LCM_E = 1;
LCM_E = 0;
for(i=0;i《100;i++);
LCM_E = 1;
return(LCM_Data);
}
//讀狀態(tài)
unsigned char ReadStatusLCM(void)
{
LCM_Data = 0xFF;
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 1;
LCM_E = 0;
for(i=0;i《100;i++);
LCM_E = 1;
//while (LCM_Data & Busy); //檢測(cè)忙信號(hào)
return(LCM_Data);
}
//寫數(shù)據(jù)
void WriteDataLCM(unsigned char WDLCM)
{
ReadStatusLCM(); //檢測(cè)忙
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RW = 0;
LCM_E = 1;
LCM_E = 0; //若晶振速度太高可以在這后加小的延時(shí)
for(i=0;i《100;i++);//延時(shí)
LCM_E = 1;
}
//寫指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC為0時(shí)忽略忙檢測(cè)
{
if (BuysC) ReadStatusLCM(); //根據(jù)需要檢測(cè)忙
LCM_Data = WCLCM;
LCM_RS = 0;
LCM_RW = 0;
LCM_E = 1;
LCM_E = 0;
for(i=0;i《100;i++);
LCM_E = 1;
}
//===========================================================
//初始化子程序
//===================================================================
void LCMInit(void) //LCM初始化
{
LCM_Data = 0;
WriteCommandLCM(0x38,0); // 三次顯示模式設(shè)置,不檢測(cè)忙信號(hào)
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,1); // 顯示模式設(shè)置,開(kāi)始要求每次檢測(cè)忙信號(hào)
Delay5Ms();
WriteCommandLCM(0x08,1); // 關(guān)閉顯示
Delay5Ms();
WriteCommandLCM(0x01,1); // 清屏 Delay5Ms();
WriteCommandLCM(0x06,1); // 顯示光標(biāo)移動(dòng)設(shè)置
Delay5Ms();
WriteCommandLCM(0x0c,1); // 顯示開(kāi)及光標(biāo)設(shè)置
Delay5Ms();
}
//================================================================
//按指定位置顯示一個(gè)字符
//===================================================================
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //當(dāng)要顯示第二行時(shí)地址碼+0x40;
X |= 0x80; //算出指令碼
WriteCommandLCM(X, 0); //這里不檢測(cè)忙信號(hào),發(fā)送地址碼
WriteDataLCM(DData);
}
//=================================================================
//按指定位置顯示一串字符
//void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
//說(shuō)明: x(0-15):x參數(shù) y(0-1):y參數(shù) DData(字符串):要顯示的內(nèi)容(英文、數(shù)字、符號(hào))
//========================================================================
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
unsigned char ListLength,j; ListLength = strlen(DData);
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (X 《= 0xF) //X坐標(biāo)應(yīng)小于0xF
? {
for(j=0;j《ListLength;j++)
? ? ?{
DisplayOneChar(X, Y, DData[j]); //顯示單個(gè)字符 X++;
? ? ?}
? }
}
//==========================================================
//顯示自定義字符
//void mychar(char xx,char yy,unsigned char *character,unsigned char saveto)
//說(shuō)明:xx(0-15):為x參數(shù).yy(0-1):y參數(shù).character:要顯示的字符的列表地址,在程序前面有定義
//saveto(1-7)為字符保存的RAM,每屏最多顯示7個(gè)自定義字符 //(0x00-0x0h是自定義字符)
//=============================================================
void mychar(char xx,char yy,unsigned char *character,unsigned char saveto)
{
unsigned char add = (saveto《《3) | 0x40;
unsigned char t; //臨時(shí)變量,每一行的值 /*
t=*(character+0);
WriteCommandLCM(add, 0); //第1行 WriteDataLCM(t); t=*(character+1);
WriteCommandLCM(add+1, 0); //第2行 WriteDataLCM(t); t=*(character+2);
WriteCommandLCM(add+2, 0); //第3行 WriteDataLCM(t); t=*(character+3);
WriteCommandLCM(add+3, 0); //第4行 WriteDataLCM(t); t=*(character+4);
WriteCommandLCM(add+4, 0); //第5行 WriteDataLCM(t); t=*(character+5);
WriteCommandLCM(add+5, 0); //第6行 WriteDataLCM(t); t=*(character+6);
WriteCommandLCM(add+6, 0); //第7行 WriteDataLCM(t); t=*(character+7);
WriteCommandLCM(add+7, 0); //第8行 WriteDataLCM(t); */
for(i = 0;i《8;i++)
{
WriteCommandLCM(add+i, 0);
WriteDataLCM(*(character+i));
}
DisplayOneChar(xx,yy,saveto); //顯示字符 }
//===============================================================
//主函數(shù)
//=========================================================
main()
{
Delay400Ms();
LCMInit();
Delay400Ms(); //1602初始化
while(1)
? {
DisplayListChar(0,0,“This is ListChar”); DisplayListChar(0,1,“!”);
for(j=0;j《30;j++)for(i=0;i《30000;i++); WriteCommandLCM(0x01,1); //清屏
Delay5Ms();
DisplayListChar(0,0,“This is OneChar:”);
DisplayOneChar(0,1,0x4f);
DisplayOneChar(1,1,0x6e);
DisplayOneChar(2,1,0x65);
DisplayOneChar(3,1,0x21);
for(j=0;j《30;j++)for(i=0;i《30000;i++);
WriteCommandLCM(0x01,1); //清屏
Delay5Ms();
DisplayListChar(0,0,“This is MyChar:”);
mychar(0,1, character0,1);
mychar(1,1, character1,2);
mychar(2,1, character2,3);
for(j=0;j《30;j++)for(i=0;i《30000;i++);
WriteCommandLCM(0x01,1); //清屏 Delay5Ms();
? }
}
評(píng)論
查看更多