畢業(yè)論文 跳繩儀設(shè)計(jì)
資源目錄里展示的全都有,所見即所得。下載后全都有,請放心下載。原稿可自行編輯修改=【QQ:401339828 或11970985 有疑問可加】
1602詳細(xì)資料和實(shí)例
1602字符液晶在實(shí)際的產(chǎn)品中運(yùn)用的也比較多了,前幾天留意了一下,發(fā)現(xiàn)宿舍門前的自動(dòng)售水機(jī)就是采用的1602液晶進(jìn)行顯示的。而且對于單片機(jī)的學(xué)習(xí)而言,掌握1602的用法是每一個(gè)學(xué)習(xí)者必然要經(jīng)歷的過程。在此,我將使用1602過程中遇到的問題以及感受記錄下來,希望能夠給初學(xué)者帶來一點(diǎn)指導(dǎo),少走一點(diǎn)彎路。
??????? 所謂1602是指顯示的內(nèi)容為16*2,即可以顯示兩行,每行16個(gè)字符。目前市面上字符液晶絕大多數(shù)是基于HD44780液晶芯片的,控制原理是完全相同的,因此基于HD44780寫的控制程序可以很方便地應(yīng)用于市面上大部分的字符型液晶。
1602液晶的正面(綠色背光,黑色字體)
1602液晶背面(綠色背光,黑色字體)
另一種1602液晶模塊,顯示屏是藍(lán)色背光白色字體
??????? 字符型LCD1602通常有14條引腳線或16條引腳線的LCD,多出來的2條線是背光電源線VCC(15腳)和地線GND(16腳),其控制原理與14腳的LCD完全一樣,引腳定義如下表所示:
??????? HD44780內(nèi)置了DDRAM、CGROM和CGRAM。?
DDRAM就是顯示數(shù)據(jù)RAM,用來寄存待顯示的字符代碼。共80個(gè)字節(jié),其地址和屏幕的對應(yīng)關(guān)系如下表:
也就是說想要在LCD1602屏幕的第一行第一列顯示一個(gè)"A"字,就要向DDRAM的00H地址寫入“A”字的代碼(指A的字模代碼,0x20~0x7F為標(biāo)準(zhǔn)的ASCII碼,通過這個(gè)代碼,在CGROM中查找到相應(yīng)的字符顯示)就行了。但具體的寫入是要按LCD模塊的指令格式來進(jìn)行的,后面我會(huì)說到的。那么一行可有40個(gè)地址呀?是的,在1602中我們就用前16個(gè)就行了。第二行也一樣用前16個(gè)地址。對應(yīng)如下:
DDRAM地址與顯示位置的對應(yīng)關(guān)系
(事實(shí)上我們往DDRAM里的00H地址處送一個(gè)數(shù)據(jù),譬如0x31(數(shù)字1的代碼,見字模關(guān)系對照表)并不能顯示1出來。這是一個(gè)令初學(xué)者很容易出錯(cuò)的地方,原因就是如果你要想在DDRAM的00H地址處顯示數(shù)據(jù),則必須將00H加上80H,即80H,若要在DDRAM的01H處顯示數(shù)據(jù),則必須將01H加上80H即81H。依次類推。大家看一下控制指令的的8條:DDRAM地址的設(shè)定,即可以明白是怎么樣的一回事了),1602液晶模塊內(nèi)部的字符發(fā)生存儲(chǔ)器(CGROM)已經(jīng)存儲(chǔ)了160個(gè)不同的點(diǎn)陣字符圖形(無漢字),如下表所示,這些字符有:阿拉伯?dāng)?shù)字、英文字母的大小寫、常用的符號、和日文假名等,每一個(gè)字符都有一個(gè)固定的代碼,比如大寫的英文字母“A”的代碼是01000001B(41H),顯示時(shí)模塊把地址41H中的點(diǎn)陣字符圖形顯示出來,我們就能看到字母“A”
?
??????? 上表中的字符代碼與我們PC中的字符代碼是基本一致的。因此我們在向DDRAM寫C51字符代碼程序時(shí)甚至可以直接用P1='A'這樣的方法。PC在編譯時(shí)就把“A”先轉(zhuǎn)為41H代碼了。?
??????? 字符代碼0x00~0x0F為用戶自定義的字符圖形RAM(對于5X8點(diǎn)陣的字符,可以存放8組,5X10點(diǎn)陣的字符,存放4組),就是CGRAM了。后面我會(huì)詳細(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條指令:
HD44780的指令集
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è)定每次寫入的一個(gè)字符是否移動(dòng)。參數(shù)設(shè)定的情況如下所示:
??????????????
????位名??????????????設(shè)置
????I/D?????????????? 0=寫入新數(shù)據(jù)后光標(biāo)左移????????????????????????????
????????????????????????1=寫入新數(shù)據(jù)后光標(biāo)右移
???? S????????????????0=寫入新數(shù)據(jù)后顯示屏不移動(dòng)
????????????????????????1=寫入新數(shù)據(jù)后顯示屏整體右移1個(gè)字
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)移動(dòng)方向指令
?
功能:使光標(biāo)移位或使整個(gè)顯示屏幕移位。參數(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)不動(dòng)
1???????????????? 1??????????顯示器上字符全部右移一格,但光標(biāo)不動(dòng)
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è)定下一個(gè)要存入數(shù)據(jù)的CGRAM的地址。
8.設(shè)定DDRAM地址指令
?功能:設(shè)定下一個(gè)要存入數(shù)據(jù)的CGRAM的地址。
(注意這里我們送地址的時(shí)候應(yīng)該是0x80+Address,這也是前面說到寫地址命令的時(shí)候要加上0x80的原因)
9.讀取忙信號或AC地址指令
??
功能:<1> 讀取忙碌信號BF的內(nèi)容,BF=1表示液晶顯示器忙,暫時(shí)無法接收單片機(jī)送來的數(shù)據(jù)或指令;
???????????????????? 當(dāng)BF=0時(shí),液晶顯示器可以接收單片機(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)容。
基本操作時(shí)序:
讀狀態(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ù)
???????????????? 輸出:無
??????? 呵呵,看到這么多的控制指令希望你沒有頭暈。其實(shí)這么多的指令剛開始的時(shí)候沒有必要全部掌握,隨著學(xué)習(xí)的深入可以再嘗試去用更復(fù)雜的控制指令。下面讓我們一起驅(qū)動(dòng)1602的液晶吧。下面是我的液晶的連接圖,用的是那種藍(lán)底白字的液晶,其實(shí)藍(lán)底白字和那種綠底黑字的液晶唯一的區(qū)別就是顏色的問題,至于用哪種液晶,就看各位自己的喜好咯。?
??????? 這就是我做測試用的最小系統(tǒng),單片機(jī)是STC89C516,晶振為12M。液晶為藍(lán)底白字的那種1602。
?
??????? 當(dāng)我們硬件連接錯(cuò)誤,或者程序錯(cuò)誤時(shí)就會(huì)出現(xiàn)下圖這種情況,就是上排顯示16的白色的塊(藍(lán)底黑字的液晶則顯示的是16個(gè)黑塊)。
??
?
??????? 下面我們來驅(qū)動(dòng)1602吧在1602的上排顯示“LCD1602 check ok”下排顯示“study up”程序中沒有用到忙檢測,而是用的是延時(shí)函數(shù)來替代忙檢測
#include?? ??//包含頭文件,這個(gè)嘛,就不用多說了~~
#define uint unsigned int??//預(yù)定義一下
#define uchar unsigned char
sbit rs=P3^5;???? //1602的數(shù)據(jù)/指令選擇控制線
sbit rw=P3^6;????????//1602的讀寫控制線
sbit en=P3^7;????????//1602的使能控制線
/*P2口接1602的D0~D7,注意不要接錯(cuò)了順序,我以前可在這上面吃過虧~*/
uchar code table[]="LCD1602 check ok"; //要顯示的內(nèi)容1放入數(shù)組table
uchar code table1[]="study up";???????????? //要顯示的內(nèi)容2放入數(shù)組table1
void delay(uint n)?????? //延時(shí)函數(shù)??????????????????????
{
????uint x,y;
????for(x=n;x>0;x--)
????????for(y=110;y>0;y--);
}
/*********************************************************************************/
l void lcd_wcom(uchar com)??//1602寫命令函數(shù)?(單片機(jī)給1602寫命令)???????????????
{ //1602接收到命令后,不用存儲(chǔ),直接由HD44780執(zhí)行并產(chǎn)生相應(yīng)動(dòng)作
????rs=0;??????????? ?//選擇指令寄存器
????rw=0;??????????? //選擇寫
????P2=com;????????????//把命令字送入P2
????delay(5);????????????//延時(shí)一小會(huì)兒,讓1602準(zhǔn)備接收數(shù)據(jù)
????en=1;?????????? //使能線電平變化,命令送入1602的8位數(shù)據(jù)口
????en=0;
}
void lcd_wdat(uchar dat)????????//1602寫數(shù)據(jù)函數(shù)??????
{
????rs=1;??????? ? //選擇數(shù)據(jù)寄存器
????rw=0;??????? ?//選擇寫
????P2=dat;????????//把要顯示的數(shù)據(jù)送入P2
????delay(5);??????//延時(shí)一小會(huì)兒,讓1602準(zhǔn)備接收數(shù)據(jù)
????en=1;??????? ?//使能線電平變化,數(shù)據(jù)送入1602的8位數(shù)據(jù)口
????en=0;
}
void lcd_init()??????????????//1602初始化函數(shù)??????
{
????lcd_wcom(0x38);?????? //8位數(shù)據(jù),雙列,5*7字形??????
????lcd_wcom(0x0c);????? ?//開啟顯示屏,關(guān)光標(biāo),光標(biāo)不閃爍
????lcd_wcom(0x06);???? //顯示地址遞增,即寫一個(gè)數(shù)據(jù)后,顯示位置右移一位
????lcd_wcom(0x01);??? ?//清屏
}
void main()????????????//主函數(shù)
{????
????uchar n,m=0;
????lcd_init();???????????????? //液晶初始化
????lcd_wcom(0x80);?? //顯示地址設(shè)為80H(即00H,)上排第一位(也是執(zhí)行一條命令)??????
????for(m=0;m<16;m++)???? //將table[]中的數(shù)據(jù)依次寫入1602顯示
????{
????????????lcd_wdat(table[m]);??????????
????????????delay(200);
????}
????lcd_wcom(0x80+0x44); //重新設(shè)定顯示地址為0xc4,即下排第5位
????for(n=0;n<8;n++)?? //將table1[]中的數(shù)據(jù)依次寫入1602顯示
????{????
????????????lcd_wdat(table1[n]);
?????????? delay(200);
????}
????while(1);????????//動(dòng)態(tài)停機(jī)
}
??????? 程序?qū)懞煤鬅龑戇M(jìn)單片機(jī),現(xiàn)在讓我們看看效果吧
?
??????? 這就是顯示的效果。
??????? 下面讓我們來看看如何顯示一個(gè)自定義的字符吧?
??????? 我們從CGROM表上可以看到,在表的最左邊是一列可以允許用戶自定義的CGRAM,從上往下看著是16個(gè),實(shí)際只有8個(gè)字節(jié)可用。它的字符碼是00000000-00000111這8個(gè)地址,表的下面還有8個(gè)字節(jié),但因?yàn)檫@個(gè)CGRAM的字符碼規(guī)定0-2位為地址,3位無效,4-7全為零。因此CGRAM的字符碼只有最后三位能用也就是8個(gè)字節(jié)了。等效為0000X111,X為無效位,最后三位為000-111共8個(gè)。?
??????? 如果我們要想顯示這8個(gè)用戶自定義的字符,操作方法和顯示CGROM的一樣,先設(shè)置DDRAM位置,再向DDRAM寫入字符碼,例如“A”就是41H?,F(xiàn)在我們要顯示CGRAM的第一個(gè)自定義字符,就向DDRAM寫入00000000B(00H),如果要顯示第8個(gè)就寫入00000111(08H),簡單吧!?
??????? 好!現(xiàn)在我們來看怎么向這八個(gè)自定義字符寫入字模。有個(gè)設(shè)置CGRAM地址的指令大家還記得嗎?趕快再找出來看看。
?
??????? 從這個(gè)指令可以看出指令數(shù)據(jù)的高2位已固定是01,只有后面的6位是地址數(shù)據(jù),而這6位中的高3位就表示這八個(gè)自定義字符,最后的3位就是字模數(shù)據(jù)的八個(gè)地址了。例如第一個(gè)自定義字符的字模地址為01000000-01000111八個(gè)地址。我們向這8個(gè)字節(jié)寫入字模數(shù)據(jù),讓它能顯示出“℃”
地址:01000000 數(shù)據(jù):00010000?????? 圖示:○○○■○○○○
01000001 00000110?????????????? ○○○○○■■○
01000010 00001001?????????????? ○○○○■○○■
01000011 00001000?????????????? ○○○○■○○○
01000100 00001000?????????????? ○○○○■○○○
01000101 00001001?????????????? ○○○○■○○■
01000110 00000110?????????????? ○○○○○■■○
01000111 00000000?????????????? ○○○○○○○○?
??????? 下面我們寫一段程序讓這8個(gè)自定義字符顯示出一個(gè)心的圖案: (由于上面那個(gè)顯示程序已經(jīng)有很詳細(xì)的注釋了,因此這個(gè)程序只對與上個(gè)程序不同的地方寫注釋)
#include
#define uint unsigned int
#define uchar unsigned char
sbit rs=P3^5;
sbit rw=P3^6;
sbit en=P3^7;
uchar code table[]={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};//心圖案
/*uchar??code table1[]={0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00};//字符℃ */
void delay(uint n)??????????????????????????????
{
????uint x,y;
????for(x=n;x>0;x--)
????????????for(y=110;y>0;y--);
}
void lcd_wcom(uchar com)??????????????????
{
????rs=0;
????rw=0;
????P2=com;
????delay(5);
????en=1;
????en=0;
}
void lcd_wdat(uchar dat)??????????????
{
????rs=1;
????rw=0;
????P2=dat;
????delay(5);
????en=1;
????en=0;
}
void lcd_init()????????????????????
{
???????? lcd_wcom(0x38);????????????
???????? lcd_wcom(0x0c);??????????
???????? lcd_wcom(0x06);????????????
???????? lcd_wcom(0x01);????????????
}
void main()
{????
????????????????????char m=0;
????lcd_init();
????lcd_wcom(0x40);???????????? //設(shè)定CGRAM地址
????for(m=0;m<64;m++)????//將心型代碼寫入CGRAM中
????{
????????????lcd_wdat(table[m]);??????????
????}
????lcd_wcom(0x85);????????//設(shè)定上排的顯示位置
????for(m=0;m<4;m++)????????//顯示心型圖案的上半部分
????{
????????????lcd_wdat(m);
????}
????lcd_wcom(0xc5);????????//將顯示坐標(biāo)轉(zhuǎn)移到下排和上排相對應(yīng)的地方
????for(m=4;m<8;m++)????????//顯示心型圖案的下半部分
????{
????????????lcd_wdat(m);
????}
????while(1);
}
讓我們一起來看看顯示的效果吧~~
在綠底黑字液晶模塊和藍(lán)底白字液晶模塊上分別顯示的效果。
下面再為大家展示幾種可能出現(xiàn)的問題?
??????? 1:通電之后,程序也燒寫進(jìn)去了,但是1602就是不顯示,只顯示一排黑塊(一般都是在上排8個(gè)小黑塊,記得剛開始用1602液晶的時(shí)候,被這個(gè)整怕了~~),怎么樣,你郁悶了吧,其實(shí)出現(xiàn)這種問題的原因無非以下幾種:硬件連線上的錯(cuò)誤,這種錯(cuò)誤一般用萬用表仔細(xì)檢查后很容易找出來。第二種情況就是硬件連接上是正確的,那么此時(shí)出問題最大的就是程序上了,如果你用的是忙檢測,看一下忙檢測函數(shù)寫對了沒,如果用的是延時(shí)函數(shù),那么看看延時(shí)的時(shí)間是否夠長。再就是看看時(shí)序圖,這點(diǎn)很重要的哦。如果硬件和軟件都沒有錯(cuò),那么就要考慮1602是否壞了,但是出現(xiàn)這種情況的幾率很小,如果遇到這種情況,你可以考慮去買彩票了~~?
??????? 下面這種情況你遇到過嗎?我遇到過了的,搞得我很是郁悶~~
?
??????? 我做的實(shí)驗(yàn)是要液晶顯示ABC這三個(gè)字母,并且開光標(biāo),光標(biāo)閃爍。大家可以在第一排的最后幾位看到ABC和光標(biāo)都已經(jīng)顯示出來了。但是為什么其它位會(huì)顯示這么多8呢?嘿嘿~~郁悶吧。出現(xiàn)這種情況的原因就是在初始化液晶的時(shí)候,要把清屏指令放在最后面,否則就會(huì)出現(xiàn)上圖這種情況。怎么樣,第一次聽說吧~不過,我不知道其它的液晶是否也有這個(gè)問題出現(xiàn),至少我用的這塊就有這種情況,但是我的另一個(gè)液晶則沒有這種情況出現(xiàn),不管是在一開始就清屏還是最后清屏。大家注意下就可以了,萬一出現(xiàn)了這種情況,就會(huì)處理了~~
?
??????? 上面這張圖是用1602作為顯示的溫度電子鐘~~上面的年月日三個(gè)字就是用自定義字符的方法顯示的。呵呵,怎么樣~~到此1602的驅(qū)動(dòng)基本上結(jié)束了,剩下的就靠大家自己去發(fā)揮了
收藏