標(biāo)題: 51單片機(jī)驅(qū)動LCD1602程序設(shè)計(jì)(C語言)很詳細(xì)的教程 [打印本頁]
作者: lugangqiang 時間: 2018-10-24 17:13
標(biāo)題: 51單片機(jī)驅(qū)動LCD1602程序設(shè)計(jì)(C語言)很詳細(xì)的教程
51單片機(jī)驅(qū)動LCD1602程序設(shè)計(jì)(C語言)
字符液晶絕大多數(shù)是基于HD44780液晶芯片的,控制原理是完全相同的,因此HD44780寫的控制程序可以很方便地應(yīng)用于市面上大部分的字符型液晶。字符型LCD通常有14條引腳線或16條引腳線的LCD,多出來的2條線是背光電源線VCC(15腳)和地線GND(16腳),其控制原理與14腳的LCD完全一樣,定義如下表所示:
字符型LCD的引腳定義

HD44780內(nèi)置了DDRAM、CGROM和CGRAM。DDRAM就是顯示數(shù)據(jù)RAM,用來寄存待顯示的字符代碼。共80個字節(jié),其地址和屏幕的對應(yīng)關(guān)系如下表:

也就是說想要在LCD1602屏幕的第一行第一列顯示一個"A"字,就要向DDRAM的00H地址寫入“A”字的代碼就行了。但具體的寫入是要按LCD模塊的指令格式來進(jìn)行的。在1602中我們用前16個就行了。第二行也一樣用前16個地址。對應(yīng)如下:
DDRAM地址與顯示位置的對應(yīng)關(guān)系

文本文件中每一個字符都是用一個字節(jié)的代碼記錄的。一個漢字是用兩個字節(jié)的代碼記錄。在PC上我們只要打開文本文件就能在屏幕上看到對應(yīng)的字符是因?yàn)樵诓僮飨到y(tǒng)里和BIOS里都固化有字符字模。什么是字模?就代表了是在點(diǎn)陣屏幕上點(diǎn)亮和熄滅的信息數(shù)據(jù)。
例如“A”字的字模:
01110 ○■■■○
10001 ■○○○■
10001 ■○○○■
10001 ■○○○■
11111 ■■■■■
10001 ■○○○■
10001 ■○○○■
上圖左邊的數(shù)據(jù)就是字模數(shù)據(jù),右邊就是將左邊數(shù)據(jù)用“○”代表0,用“■”代表1。看出是個“A”字了嗎?在文本文件中“A”字的代碼是41H,PC收到41H的代碼后就去字模文件中將代表A字的這一組數(shù)據(jù)送到顯卡去點(diǎn)亮屏幕上相應(yīng)的點(diǎn),你就看到“A”這個字了。
剛才說了想要在LCD1602屏幕的第一行第一列顯示一個"A"字,就要向DDRAM的00H地址寫入“A”字的代碼41H就行了,可41H這一個字節(jié)的代碼如何才能讓LCD模塊在屏幕的陣點(diǎn)上顯示“A”字呢?同樣,在LCD模塊上也固化了字模存儲器,這就是CGROM和CGRAM。HD44780內(nèi)置了192個常用字符的字模,存于字符產(chǎn)生器CGROM(Character Generator ROM)中,另外還有8個允許用戶自定義的字符產(chǎn)生RAM,稱為CGRAM(Character Generator RAM)。下圖說明了CGROM和CGRAM與字符的對應(yīng)關(guān)系。
從上圖可以看出,“A”字的對應(yīng)上面高位代碼為0100,對應(yīng)左邊低位代碼為0001,合起來就是01000001,也就是41H?梢娝拇a與我們PC中的字符代碼是基本一致的。因此我們在向DDRAM寫C51字符代碼程序時甚至可以直接用P1='A'這樣的方法。PC在編譯時就把“A”先轉(zhuǎn)為41H代碼了。
字符代碼0x00~0x0F為用戶自定義的字符圖形RAM(對于5X8點(diǎn)陣的字符,可以存放8組,5X10點(diǎn)陣的字符,存放4組),就是CGRAM了。后面我會詳細(xì)說的。
0x20~0x7F為標(biāo)準(zhǔn)的ASCII碼,0xA0~0xFF為日文字符和希臘文字符,其余字符碼(0x10~0x1F及0x80~0x9F)沒有定義。
那么如何對DDRAM的內(nèi)容和地址進(jìn)行具體操作呢,下面先說說HD44780的指令集及其設(shè)置說明,請瀏覽該指令集,并找出對DDRAM的內(nèi)容和地址進(jìn)行操作的指令。共11條指令:
1.清屏指令

功能:<1> 清除液晶顯示器,即將DDRAM的內(nèi)容全部填入"空白"的ASCII碼20H;
<2> 光標(biāo)歸位,即將光標(biāo)撤回液晶顯示屏的左上方;
<3> 將地址計(jì)數(shù)器(AC)的值設(shè)為0。
2.光標(biāo)歸位指令

功能:<1> 把光標(biāo)撤回到顯示器的左上方;
<2> 把地址計(jì)數(shù)器(AC)的值設(shè)置為0;
<3> 保持DDRAM的內(nèi)容不變。
3.進(jìn)入模式設(shè)置指令

功能:設(shè)定每次定入1位數(shù)據(jù)后光標(biāo)的移位方向,并且設(shè)定每次寫入的一個字符是否移動。參數(shù)設(shè)定的
情況如下所示:
位名 設(shè)置
I/D 0=寫入新數(shù)據(jù)后光標(biāo)左移 1=寫入新數(shù)據(jù)后光標(biāo)右移
S 0=寫入新數(shù)據(jù)后顯示屏不移動 1=寫入新數(shù)據(jù)后顯示屏整體右移1個字符
4.顯示開關(guān)控制指令

功能:控制顯示器開/關(guān)、光標(biāo)顯示/關(guān)閉以及光標(biāo)是否閃爍。參數(shù)設(shè)定的情況如下:
位名 設(shè)置
D 0=顯示功能關(guān) 1=顯示功能開
C 0=無光標(biāo) 1=有光標(biāo)
B 0=光標(biāo)閃爍 1=光標(biāo)不閃爍
5.設(shè)定顯示屏或光標(biāo)移動方向指令

功能:使光標(biāo)移位或使整個顯示屏幕移位。參數(shù)設(shè)定的情況如下:
S/C R/L 設(shè)定情況
0 0 光標(biāo)左移1格,且AC值減1
0 1 光標(biāo)右移1格,且AC值加1
1 0 顯示器上字符全部左移一格,但光標(biāo)不動
1 1 顯示器上字符全部右移一格,但光標(biāo)不動
6.功能設(shè)定指令

功能:設(shè)定數(shù)據(jù)總線位數(shù)、顯示的行數(shù)及字型。參數(shù)設(shè)定的情況如下:
位名 設(shè)置
DL 0=數(shù)據(jù)總線為4位 1=數(shù)據(jù)總線為8位
N 0=顯示1行 1=顯示2行
F 0=5×7點(diǎn)陣/每字符 1=5×10點(diǎn)陣/每字符
7.設(shè)定CGRAM地址指令

功能:設(shè)定下一個要存入數(shù)據(jù)的CGRAM的地址。
8.設(shè)定DDRAM地址指令
功能:設(shè)定下一個要存入數(shù)據(jù)的CGRAM的地址。
9.讀取忙信號或AC地址指令

功能:<1> 讀取忙碌信號BF的內(nèi)容,BF=1表示液晶顯示器忙,暫時無法接收單片機(jī)送來的數(shù)據(jù)或指令;當(dāng)BF=0時,液晶顯示器可以接收單片機(jī)送來的數(shù)據(jù)或指令;
<2> 讀取地址計(jì)數(shù)器(AC)的內(nèi)容。
10.數(shù)據(jù)寫入DDRAM或CGRAM指令一覽

功能:<1> 將字符碼寫入DDRAM,以使液晶顯示屏顯示出相對應(yīng)的字符;
<2> 將使用者自己設(shè)計(jì)的圖形存入CGRAM。
11.從CGRAM或DDRAM讀出數(shù)據(jù)的指令一覽

功能:讀取DDRAM或CGRAM中的內(nèi)容。
基本操作時序:
讀狀態(tài) 輸入:RS=L,RW=H,E=H 輸出:DB0~DB7=狀態(tài)字
寫指令 輸入:RS=L,RW=L,E=下降沿脈沖,DB0~DB7=指令碼 輸出:無
讀數(shù)據(jù) 輸入:RS=H,RW=H,E=H 輸出:DB0~DB7=數(shù)據(jù)
寫數(shù)據(jù) 輸入:RS=H,RW=L,E=下降沿脈沖,DB0~DB7=數(shù)據(jù) 輸出:無
顯示操作的過程:首先確認(rèn)顯示的位置,即在第幾行,第幾個字符開始顯示。也就是要顯示的地址,如下表所示的顯示地址。
第一行的顯示地址是0x80-0x8F,第二行的顯示地址是0xC0-0xCF。例如想要在第2行,第3個位置顯示一個字符,那么地址碼就是0xC2。在編程過程中,通常編寫一個函數(shù)確定在某行某個位置顯示[url=]數(shù)據(jù)[/url]。函數(shù)需要 行[url=]參數(shù)[/url](y),和 列參數(shù)(x)來確定顯示位置。[url=]程序[/url]參考如下
/***************設(shè)置顯示位置**************************/
void LCD_set_xy( unsigned char x, unsigned char y )
{
unsigned char address;
if (0 == y) x |= 0x80; //當(dāng)要顯示第一行時地址碼+0x80;
else x |= 0xC0; //在第二行顯示是地址碼+0xC0;
Write_com(x); //發(fā)送地址碼 0x80-0x8F 或者0xC0-0xCF
}
其次設(shè)置要顯示的內(nèi)容,即上面提到的CGROM內(nèi)的字符編碼。如顯示“A”,將編碼41H寫入到液晶屏顯示即可。通常設(shè)置地址和顯示內(nèi)容用一個函數(shù)來完成。代碼參考如下:
//功能:按指定位置顯示一個字符
//輸入:列顯示地址x(取值范圍0-15) 行顯示地址y(取值范圍0-1), 指定字符
void DisplayOneChar(unsigned char x, unsigned char y, unsigned char Data)
{
if (0 == y) x |= 0x80; //當(dāng)要顯示第一行時地址碼+0x80;
else x |= 0xC0; //在第二行顯示是地址碼+0xC0;
Write_com(x); //發(fā)送地址碼
Write_dat(Data); //發(fā)送要顯示的字符編碼
}
顯示字符“A”調(diào)用過程如下代碼:
DisplayOneChar(0,0,0x41);
//功能:在第1行 第1個字符 顯示一個大寫字母A
在C語言操作時,還可以顯示整個字符串。定義一個字符串顯示函數(shù),可
以通過直接輸入字符方式進(jìn)行顯示
//功能:按指定位置顯示一串字符
//輸入:列顯示地址x(取值范圍0-15) 行顯示地址y(取值范圍0-1), 指定字符串指針*p,要顯示的字符個數(shù)count (取值范圍1-16)
void DisplayListChar (unsigned char x,unsigned char y,unsigned char *p,unsigned char count)
{
unsigned char i;
for(i=0;i<count;i++)
{
if (0 == y) x |= 0x80; //當(dāng)要顯示第一行時地址碼+0x80;
else x |= 0xC0; //在第二行顯示是地址碼+0xC0;
Write_com(x); //發(fā)送地址碼
Write_dat(*p); //發(fā)送要顯示的字符編碼
x++;
p++;
}
}
調(diào)用方法如下:
DisplayListChar(0,0,"hello world",11); //液晶1602第一行顯示
DisplayListChar(0,1,"www*qm999*cn",12); //液晶1602第二行顯示
舉個實(shí)例,就在LCD1602屏幕上第一行第一列顯示個“A”字。
- //先定義接口
- # include <AT89x51.h>
- /*****************************************
- P1------DB0~DB7
- P2.0------RS
- P2.1------RW
- P2.2------E
- *****************************************/
- # define LCD_DB P1
- sbit LCD_RS=P2^0;
- sbit LCD_RW=P2^1;
- sbit LCD_E=P2^2;
- /******定義函數(shù)****************/
- # define uchar unsigned char
- # define uint unsigned int
- void LCD_init(void);//初始化函數(shù)
- void LCD_write_command(uchar command);//寫指令函數(shù)
- void LCD_write_data(uchar dat);//寫數(shù)據(jù)函數(shù)
- void LCD_disp_char(uchar x,uchar y,uchar dat);//在某個屏幕位置上顯示一個字符,X(0-16),y(1-2)
- //void LCD_check_busy(void);//檢查忙函數(shù)。我沒用到此函數(shù),因?yàn)橥ㄟ^率極低。
- void delay_n40us(uint n);//延時函數(shù)
- //********************************
- //*******初始化函數(shù)***************
- void LCD_init(void)
- {
- LCD_write_command(0x38);//設(shè)置8位格式,2行,5x7
- LCD_write_command(0x0c);//整體顯示,關(guān)光標(biāo),不閃爍
- LCD_write_command(0x06);//設(shè)定輸入方式,增量不移位
- LCD_write_command(0x01);//清除屏幕顯示
- delay_n40us(100);//實(shí)踐證明,用for循環(huán)200次就能可靠完成清屏指令。
- }
- //********************************
- //********寫指令函數(shù)************
- void LCD_write_command(uchar dat)
- {
- LCD_DB=dat;
- LCD_RS=0;//指令
- LCD_RW=0;//寫入
- LCD_E=1;//允許
- LCD_E=0;
- delay_n40us(1);//實(shí)踐證明,我的LCD1602上,用for循環(huán)1次就能完成普通寫指令。
- }
- //*******************************
- //********寫數(shù)據(jù)函數(shù)*************
- void LCD_write_data(uchar dat)
- {
- LCD_DB=dat;
- LCD_RS=1;//數(shù)據(jù)
- LCD_RW=0;//寫入
- LCD_E=1;//允許
- LCD_E=0;
- delay_n40us(1);
- }
- //********************************
- //*******顯示一個字符函數(shù)*********
- void LCD_disp_char(uchar x,uchar y,uchar dat)
- {
- uchar address;
- if(y==1)
- address=0x80+x;
- else
- address=0xc0+x;
- LCD_write_command(address);
- LCD_write_data(dat);
- }
- //********************************
- /*******檢查忙函數(shù)*************
- void LCD_check_busy() //實(shí)踐證明,在我的LCD1602上,檢查忙指令通過率極低,以
- { //至于不能正常使用LCD。因此我沒有再用檢查忙函數(shù)。而使
- do //用了延時的方法,延時還是非常好用的。我試了一下,用
- { LCD_E=0; //for循環(huán)作延時,普通指令只要1次循就可完成。清屏指令
- LCD_RS=0; //要用200次循環(huán)便能完成。
- LCD_RW=1;
- LCD_DB=0xff;
- LCD_E=1;
- }while(LCD_DB^7==1);
- }
- ******************************/
- //********延時函數(shù)***************
- void delay_n40us(uint n)
- { uint i;
- uchar j;
- for(i=n;i>0;i--)
- for(j=0;j<2;j++); //在這個延時循環(huán)函數(shù)中我只做了2次循環(huán),
- } //實(shí)踐證明我的LCD1602上普通的指令只需1次循環(huán)就能可靠完成。
- //*******************************
- //*********主函數(shù)*****************
- void main(void)
- {
- LCD_init();
- LCD_disp_char(0,1,’A’);
- while(1);
- }
- //*******************************
復(fù)制代碼
具體電路的制作是很簡單的,就接了兩個電阻,一個是10歐姆的背光限流電阻,另一個是2K的LCD極板電壓調(diào)節(jié)電阻。這兩個電阻的阻值怎么定呢?背光比較簡單,它就相當(dāng)于在后面接了幾個發(fā)光二極管,任何時候你只要在15、16腳串上個100歐的電位器接上電源,調(diào)節(jié)電位器,覺得亮度合適。此時的阻值便可。LCD液晶極板驅(qū)動電壓調(diào)節(jié)電阻的確定就稍微麻煩一點(diǎn)。在各數(shù)據(jù)線,控制線接好關(guān)通上電源的前提下在第3腳(VEE)和地之間接一個10K的電位器。調(diào)節(jié)電位器。當(dāng)3腳電壓高時為全亮,電壓為0時為全暗(液晶全顯示為黑塊)。你用電位器把屏幕從全暗剛好調(diào)到變亮。這時便可調(diào)試程序。待屏幕能正確顯示后再細(xì)調(diào)電位器,使對比度合適。這時的阻值便可確定,然后換成等值的固定電阻焊上便可。


組裝后:

具體電路圖:

接口說明:

我們從CGROM表上可以看到,在表的最左邊是一列可以允許用戶自定義的CGRAM,從上往下看著是16個,實(shí)際只有8個字節(jié)可用。它的字符碼是00000000-00000111這8個地址,表的下面還有8個字節(jié),但因?yàn)檫@個CGRAM的字符碼規(guī)定0-2位為地址,3位無效,4-7全為零。因此CGRAM的字符碼只有最后三位能用也就是8個字節(jié)了。等效為0000X111,X為無效位,最后三位為000-111共8個。
如果我們要想顯示這8個用戶自定義的字符,操作方法和顯示CGROM的一樣,先設(shè)置DDRAM位置,再向DDRAM寫入字符碼,例如“A”就是41H,F(xiàn)在我們要顯示CGRAM的第一個自定義字符,就向DDRAM寫入00000000B(00H),如果要顯示第8個就寫入00000111(08H),簡單吧!
現(xiàn)在我們來看怎么向這八個自定義字符寫入字模。有個設(shè)置CGRAM地址的指令大家還記得嗎?趕快再找出來看看。

從這個指令可以看出指令數(shù)據(jù)的高2位已固定是01,只有后面的6位是地址數(shù)據(jù),而這6位中的高3位就表示這八個自定義字符,最后的3位就是字模數(shù)據(jù)的八個地址了。例如第一個自定義字符的字模地址為01000000-01000111八個地址。我們向這8個字節(jié)寫入字模數(shù)據(jù),讓它能顯示出“℃”
地址:01000000 數(shù)據(jù):00010000 圖示:○○○■○○○○
01000001 00000110 ○○○○○■■○
01000010 00001001 ○○○○■○○■
01000011 00001000 ○○○○■○○○
01000100 00001000 ○○○○■○○○
01000101 00001001 ○○○○■○○■
01000110 00000110 ○○○○○■■○
01000111 00000000 ○○○○○○○○
可以通過手動提取的方法。如下圖所示,對應(yīng)一個字符顯示區(qū)域。每8個字節(jié),組成一個點(diǎn)陣數(shù)組。

“日”的點(diǎn)陣數(shù)組即為 {0x1f,0x11,0x11,0x1f,0x11,0x11,0x1f,0x00}

“車”字取模數(shù)組為:{0x00,0x0f,0x02,0x04,0x07,0x00,0x0f,0x00,
0x10,0x1e,0x00,0x10,0x1c,0x10,0x1e,0x10}
將生成的點(diǎn)陣數(shù)組保存到CGRAM存儲器中,生成自定義字符。1602內(nèi)部CGRAM用于自定義的字符點(diǎn)陣的存儲,總共64字節(jié)。由上一步點(diǎn)陣提取可知,每一個字符由8個字節(jié)數(shù)據(jù)組成。所以64字節(jié)CGRAM存儲器,能夠存儲8組自定義字符的點(diǎn)陣數(shù)組。按照CGRAM地址劃分為0-7為第一組,8-15為第二組,依次類推56-63為第8組數(shù)據(jù)。把自定義字符的數(shù)組按8個字節(jié)一組存儲到CGRAM中,程序代碼參考如下。
//功能:將自定義字符的編碼數(shù)組 寫入到CGRAM中.
//輸入:自定義字符的編碼數(shù)組
void Write_CGRAM(unsigned char *p)
{
unsigned char i,j,kk;
unsigned char tmp=0x40; //操作CGRAM的命令碼
kk=0;
for(j=0;j<8;j++) //64 字節(jié)存儲空間,可以生成 8 個自定義字符點(diǎn)陣
{
for(i=0;i<8;i++) // 8 個字節(jié)生成 1 個字符點(diǎn)陣
{
Write_com(tmp+i); //操作CGRAM的命令碼+寫入CGRAM地址.
Write_dat(p[kk]); //寫入數(shù)據(jù)
kk++;
}
tmp += 8;
}
}
上一步中,自定義字符存儲到CGRAM的任意一組以后,每一個組(8個字節(jié))也有一個顯示編碼。按順序依次為00H-07H 。顯示時,只要調(diào)用每一組的編碼,即可以顯示相應(yīng)的字符。
注:內(nèi)部常用字符顯示時,顯示編碼是從0x20開始的。0x00-0x0f是專門留給自定義字符顯示的。0x00-0x07和0x08-0x0f內(nèi)容是一樣的。例如:調(diào)用0x01 位置和0x09位置,顯示的內(nèi)容是一樣的。
直接按照單個字符的顯示方式調(diào)用顯示函數(shù),就可以顯示自定義字符了。代碼參考如下:
//在第1行,第7個位置顯示自定義漢字 “年”
DisplayOneChar(6,0,0); //顯示 "年" //CGRAM 碼 00
說明:此時“年”的8個字節(jié)點(diǎn)陣數(shù)組 ,存儲空間為CGRAM的 00-07地址
也就是CGRAM的第1組數(shù)據(jù)存儲區(qū)域,編碼為0。 如果存儲在CGRAM的08-15地址,那么編碼就應(yīng)該是 1了。
很多資料中,都沒有詳細(xì)介紹過CGRAM和CGROM的區(qū)別和用法,在1602調(diào)試過程中經(jīng)常會被搞混。這里總結(jié)一點(diǎn)小技巧,希望能給需要的人一點(diǎn)幫助。
以下是顯示效果:
單個和兩個點(diǎn)陣的漢字顯示:
圖形顯示效果:
下面一段程序讓這8個自定義字符顯示出一個心的圖案:
- #include <reg51.h>
- unsigned char table1[]={0x03,0x07,0x0f,0x1f,0x1f,0x1f,0x1f,0x1f,
- 0x18,0x1E,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
- 0x07,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
- 0x10,0x18,0x1c,0x1E,0x1E,0x1E,0x1E,0x1E,
- 0x0f,0x07,0x03,0x01,0x00,0x00,0x00,0x00,
- 0x1f,0x1f,0x1f,0x1f,0x1f,0x0f,0x07,0x01,
- 0x1f,0x1f,0x1f,0x1f,0x1f,0x1c,0x18,0x00,
- 0x1c,0x18,0x10,0x00,0x00,0x00,0x00,0x00};//心圖案
- unsigned char table[]={0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00};//字符℃
- #define CLEARSCREEN LCD_write_command(0x01)
- /**************定義接口************************/
- #define LCDIO P2
- sbit LCD1602_RS=P3^0;
- sbit LCD1602_RW=P3^1;
- sbit LCD1602_EN=P3^2;
- /**************定義函數(shù)************************/
- void LCD_write_command(unsigned char command);//寫入指令函數(shù)
- void LCD_write_dat(unsigned char dat);//寫入數(shù)據(jù)函數(shù)
- void LCD_set_xy( unsigned char x, unsigned char y );//設(shè)置顯示位置函數(shù)
- void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat);//顯示一個字符函數(shù)
- void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s);//顯示字符串函數(shù)
- void LCD_init(void);//初始化函數(shù)
- void delay_nms(unsigned int n);//延時函數(shù)
- /********************************************/
- /************初始化函數(shù)****************/
- void LCD_init(void)
- {
- CLEARSCREEN;//clear screen
- LCD_write_command(0x38);//set 8 bit data transmission mode
- LCD_write_command(0x0c);//open display (enable lcd display)
- LCD_write_command(0x80);//set lcd first display address
- CLEARSCREEN;//clear screen
- }
- /****************************************************/
- /**************寫指令函數(shù)********************************/
- void LCD_write_command(unsigned char command)
- {
- LCDIO=command;
- LCD1602_RS=0;
- LCD1602_RW=0;
- LCD1602_EN=0;
- LCD1602_EN=1;
- delay_nms(10);
- }
- /***************************************************/
- /****************寫數(shù)據(jù)函數(shù)************************/
- void LCD_write_dat(unsigned char dat)
- {
- LCDIO=dat;
- LCD1602_RS=1;
- LCD1602_RW=0;
- LCD1602_EN=0;
- delay_nms(1);
- LCD1602_EN=1;
- }
- /****************************************************/
- /***************設(shè)置顯示位置**************************/
- void LCD_set_xy( unsigned char x, unsigned char y )
- {
- unsigned char address;
- if (y == 1)
- address = 0x80 + x;
- else
- address =0xc0+ x;
- LCD_write_command(address);
- }
- /***************************************************/
- /****************顯示一個字符**********************/
- void LCD_dsp_char( unsigned x,unsigned char y,unsigned char dat)
- {
- LCD_set_xy( x, y );
- LCD_write_dat(dat);
- }
- /**********************************************/
- /***************顯示字符串函數(shù)***************/
- void LCD_dsp_string(unsigned char X,unsigned char Y,unsigned char *s)
- {
- LCD_set_xy( X, Y );
- while (*s)
- {
- LCD_write_dat(*s);
- s ++;
- }
- }
- /***********************************************/
- /********** 延時**********************/
- void delay_nms(unsigned int n)
- {
- unsigned int i=0,j=0;
- for (i=n;i>0;i--)
- for (j=0;j<10;j++);
- }
- /**************************************/
- /***********主函數(shù)**************/
- void main(void)
- {
- unsigned char i,j,k,tmp;
- LCD_init();
- delay_nms(100);
- tmp=0x40;//設(shè)置CGRAM地址的格式字
- k=0;
- for(j=0;j<8;j++)
- {
- for(i=0;i<8;i++)
- {
- LCD_write_command(tmp+i); // 設(shè)置自定義字符的 CGRAM 地址
- delay_nms(2);
- LCD_write_dat(table1[k]); // 向CGRAM寫入自定義字符表的數(shù)據(jù)
- k++;
- delay_nms(2);
- }
- tmp=tmp+8;
- }
- LCD_dsp_string(1,1,"LCD TEST ");//在第一行第一列顯示“LCD TEST”
- LCD_dsp_string(1,2,"SUCCESSFUL ");//在第二行第一列顯示“SUCCESSFUL”
- for (i=0;i<4;i++)
- {
- LCD_dsp_char( 12+i,1,i);//在第一行第12列位置顯示心圖案的上半部
- delay_nms(1);
- }
- for (i=4;i<8;i++)
- {
- LCD_dsp_char( 12+i-4,2,i);在第二行第12列位置顯示心圖案的下半部
- delay_nms(1);
- }
- while (1);
- }
- /********************************************************************/
復(fù)制代碼
實(shí)際效果如圖:

LCD1602編程實(shí)例詳見附件
完整的Word格式文檔51黑下載地址:
作者: 超級無敵酷 時間: 2018-11-7 19:56
求仿真圖
作者: damao666 時間: 2019-4-15 13:18
真的有用,很詳細(xì)而且也很容易理解,謝謝!
作者: ptlantu 時間: 2019-4-15 16:08
感謝分享,收藏
作者: 咚咚咚哈 時間: 2019-5-16 19:38
實(shí)驗(yàn)成功了,謝謝分享
作者: 今天也要努力鴨 時間: 2019-5-30 15:48
很詳細(xì)!非常感謝——
作者: Amber815 時間: 2019-7-19 15:05
單片機(jī)除了cd沒有接任何外圍電路,LCD是不是顯示不出程序里的字符?
作者: 大白菜啊 時間: 2019-8-27 11:51
注意若要顯示第二行字,有時需要0x38初始化兩次以上才行。。。。
作者: angleseed 時間: 2019-8-27 12:08
相當(dāng)?shù)脑敿?xì) 適合初學(xué)者學(xué)習(xí)學(xué)習(xí)
作者: 2672173804 時間: 2019-8-27 12:48
不會有求指教
作者: szzxl10 時間: 2019-8-27 17:18
很詳細(xì)!非常感謝
作者: aatcs 時間: 2019-9-1 07:41
哎!只能先照著寫寫看,寫多了應(yīng)該能明白
作者: jack丶 時間: 2019-10-22 20:58
厲害了,趕緊學(xué)習(xí)下
作者: pcybb 時間: 2019-11-7 18:07
大佬就是不一樣
作者: rsx9583 時間: 2019-11-7 21:29
1寫得深入淺出,很容易理解。學(xué)習(xí)了
作者: wdliming 時間: 2019-11-14 13:10
謝謝分享~~
作者: OHHO 時間: 2020-3-4 15:32
帖子例程里面指令函數(shù)E使能的下降沿中間加延時比函數(shù)最后加延時要好,但是那個時間需要根據(jù)參數(shù)調(diào)整一下。我一開始也是copy過去只能寫一行,修改了以后就比較穩(wěn)定了,感覺還是那個下降沿讀的問題吧。
初學(xué)者,不一定正確。
作者: 972963 時間: 2020-3-4 17:19
感謝樓主的熱心分享
作者: kevintang 時間: 2020-3-4 21:38
感謝分享,收藏。
作者: y123chiang 時間: 2020-3-5 19:57
謝謝提供資料.....
作者: hbcqd 時間: 2020-3-9 21:15
比郭師傅講的還詳細(xì),適合我學(xué)習(xí),謝謝分享!
作者: zgy1789 時間: 2020-4-19 14:20
這個確實(shí)詳細(xì),不錯
作者: bg4rfb 時間: 2020-4-19 18:10
這個確實(shí)詳細(xì),學(xué)習(xí)了!
作者: cheney03 時間: 2020-5-28 01:32
很詳細(xì),學(xué)習(xí)中
作者: yaoyaomeng 時間: 2020-6-3 10:38
學(xué)到了很多
作者: shundeok 時間: 2020-6-15 16:36
給力,省了自己很多麻煩,站 在巨人身上就是好
作者: 欣語寶貝 時間: 2020-6-15 20:59
受教了
作者: 13565832408 時間: 2020-7-13 14:02
我這邊什么也看不到啊,下載的文件也沒了
作者: grandpenguin 時間: 2020-7-17 10:49
關(guān)于LCD1602介紹可算是非常詳細(xì)了,分享的程序也能用,非常感謝~
作者: Jeff_BlindCat 時間: 2020-7-17 21:51
很詳細(xì)的內(nèi)容講解,從原理到demo,好貼加分。
作者: 8imi8 時間: 2020-7-19 06:15
感謝分享!收藏了
作者: bfzy123 時間: 2020-7-21 13:29
寫的非常全,非常詳細(xì),樓主是用了心分享的,感謝你,對于我這樣的新手太有幫助了,感謝您的分享!
作者: 122429 時間: 2020-7-21 17:30
void Common_Init() { Phase = 0; NextPhase = 0; TuneDutyRatioCnt = 0; PWMDutyCycle = PWM_DUTYCYCLE_05; CurrentPgaSample = 0; CurrentSample = 0; // 電流采樣值 VoltageSample = 0; // 電壓采樣值 UserSpeedSample = 0; ADCIntProtectCnt = 0; flag_ADCSample = 0; flag_ErrorException = 0; LastPhase = 0; SamePhaseCnt = 0; flag_SpeedTime = 0; SpeedTimeCnt = 0; SpeedTime = 0; SpeedTimeTemp = 0; SpeedTimeSum = 0; MotorSpeed = 0; UserRequireSpeed = 0; // 用戶請求轉(zhuǎn)速 RheostatCnt = 0; VoltageProCnt = 0; CurrentPgaProCnt = 0; CurrentProCnt = 0; #if(SENSORMODE) NowHallState = 0; PreHallState = 0; flag_HallStateRight = 0;
作者: bfzy123 時間: 2020-7-21 18:30
寫的很詳細(xì),可惜我還是不懂,門外漢。慢慢的琢磨
作者: 米花卷 時間: 2021-3-13 10:22
復(fù)制了仿真,只顯示一行,然后看回帖,說的0x38復(fù)位兩次,不明白,然后把這句(LCD_write_command(0x38);//set 8 bit data transmission mode)復(fù)制了粘貼下一行,就可以顯示兩行了。原理不懂
作者: 505877069 時間: 2023-6-27 17:13
有沒有最下面心形圖案對應(yīng)的仿真電路圖,我這圖連接有問題
作者: joyb 時間: 2023-7-3 09:08
這個教程很詳細(xì)
作者: suiwinder 時間: 2023-7-6 10:15
很仔細(xì),不過背景里面老有張圖片,不知道怎么消除啊
作者: liu6590999 時間: 2024-3-16 13:27
看的眼花了
作者: 南-wgw 時間: 2024-3-25 16:42
很詳細(xì),對我很有幫助
作者: 三極管一樣的人 時間: 2024-3-26 13:23
詳細(xì)之極,下載學(xué)習(xí),謝謝分享
歡迎光臨 (http://www.torrancerestoration.com/bbs/) |
Powered by Discuz! X3.1 |