LCD1602顯示漢字

利用1602顯示漢字也不是新鮮的內容,今天不想頹廢了。只是需要自己事先定義一下
漢字的字模,就是顯示出來的漢子字體結構。

要定義字模就需要知道1602CG RAM地址和顯示字符的地址 DD RAM
1
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



第一行第一個字符的地址是
( 0x80) ,後面的字符地址以此類推
第二行第一個字符的地址爲
( 0x80 + 0x40),需要在第一行的基地址後面加上一個偏移
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()
是寫入指令的函數, OUTD()是寫入數據的函數。







如:
左上角第一個5*7的顯示數據爲:

0x00,0x01,0x81,0x12,0x24,0x41,0x81,0x10
藍色區域的相應位爲
1
這樣就可以寫出全部
45*7點陣的顯示數據了,把它封裝在一個數組中,如數組,
hanzi[]={0x00,0x01,0x81,0x12,0x24,0x41,0x81,0x10,

……

……
……
}

之後利用命令:

OUTI(0X40);
for (i=0;i<64;i++)
{ OUTD(neu[i]);}

將這個數組中的數據賦值到
1602內部CGRAM中。完成後,再設置數據在1602上的
顯示地址,根據圖
1的結構,設置好位置,如在第一行第一個字符和第二個字符以及第二行
第一個字符和第二個字符處顯示:

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()
的作用是設置顯示的起始地址,data_out()的作用是將hanzi[]數組中的16
進制數據發送出去,每一個
16進制數字對應之5*7點陣上的每一行內容。第1行第1個字
符需要
816進制數據,第1行第2個字符處也需要816進制數據。還有第2行的兩個字
符點陣,這樣顯示一個漢字需要
3216進制數據。

 

下面列舉一個實例(proteus仿真通過)

 

 

//***************************************************************************************
//硬件連接:1602VDD接5V,VO接地,BL1接5V,BL2接地,8根數據線接P0口,RS RW E分別接P2.0、P2.1、P.4口
//***************************************************************************************
#include <reg52.h>
#include <string.h>
#define Busy 0x80 //用於檢測LCM狀態字中的Busy標識
#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}; //日
//=====================================================================================


//=====================================================================================
//延時程序
//=====================================================================================
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--);
};
}


//=====================================================================================
//讀寫子程序
//=====================================================================================

//讀數據
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);
}

//讀狀態
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); //檢測忙信號
return(LCM_Data);
}
//寫數據
void WriteDataLCM(unsigned char WDLCM)
{
ReadStatusLCM(); //檢測忙
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RW = 0;
LCM_E = 1;
LCM_E = 0; //若晶振速度太高可以在這後加小的延時
for(i=0;i<100;i++);//延時
LCM_E = 1;
}

//寫指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC爲0時忽略忙檢測
{
if (BuysC) ReadStatusLCM(); //根據需要檢測忙
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); // 三次顯示模式設置,不檢測忙信號
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,1); // 顯示模式設置,開始要求每次檢測忙信號
Delay5Ms();
WriteCommandLCM(0x08,1); // 關閉顯示
Delay5Ms();
WriteCommandLCM(0x01,1); // 清屏
Delay5Ms();
WriteCommandLCM(0x06,1); // 顯示光標移動設置
Delay5Ms();
WriteCommandLCM(0x0c,1); // 顯示開及光標設置
Delay5Ms();
}


//=====================================================================================
//按指定位置顯示一個字符
//=====================================================================================

void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大於15,Y不能大於1
if (Y) X |= 0x40; //當要顯示第二行時地址碼+0x40;
X |= 0x80; //算出指令碼
WriteCommandLCM(X, 0); //這裏不檢測忙信號,發送地址碼
WriteDataLCM(DData);
}

//=====================================================================================
//按指定位置顯示一串字符
//void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
//說明: x(0-15):x參數 y(0-1):y參數 DData(字符串):要顯示的內容(英文、數字、符號)
//=====================================================================================

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座標應小於0xF
        {
      for(j=0;j<ListLength;j++)
        {
             DisplayOneChar(X, Y, DData[j]); //顯示單個字符
             X++;
            }
        }
}

//=====================================================================================
//顯示自定義字符
//void mychar(char xx,char yy,unsigned char *character,unsigned char saveto)
//說明:xx(0-15):爲x參數.yy(0-1):y參數.character:要顯示的字符的列表地址,在程序前面有定義
//saveto(1-7)爲字符保存的RAM,每屏最多顯示7個自定義字符
//(0x00-0x0h是自定義字符)
//=====================================================================================

void mychar(char xx,char yy,unsigned char *character,unsigned char saveto)
{
unsigned char add = (saveto<<3) | 0x40;
unsigned char t;      //臨時變量,每一行的值

/*

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);    //顯示字符
}
//=====================================================================================
//主函數
//=====================================================================================

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();
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章