|
由于市面上常見(jiàn)的字符型液晶驅(qū)動(dòng)器均由HD44780或其兼容芯片構(gòu)成,因此,這類(lèi)液晶屏的驅(qū)動(dòng)程序具有一定的通用性,這里給出用C語(yǔ)言寫(xiě)的驅(qū)動(dòng)程序。 在設(shè)置字符的起始行、列后,直接調(diào)用驅(qū)動(dòng)程序提供的WriteString函數(shù)即可將字符串顯示在指定的位置,使用非常簡(jiǎn)單。在熟悉了程序后,略作改動(dòng), 可用于2002、2004等型號(hào)的液晶屏。 /************************************************** * 平凡單片機(jī)工作室 * http://www.mcustudio.com * Copyright 2003 pingfan's McuStudio * All rights Reserved *作者:周堅(jiān) *yj.c *連線(xiàn)圖: * DB0---DPROT.0 DB4---DPROT.4 RS-------------P2.5 * DB1---DPROT.1 DB5---DPROT.5 RW-------------P2.6 * DB2---DPROT.2 DB6---DPROT.6 E--------------P2.7 * DB3---DPROT.3 DB7---DPROT.7 VLCD接10K可調(diào)電阻到GND* *80C51的晶振頻率為12MHz *液晶顯示程序 ***************************************************/ #include "reg51.h" #include<absacc.h> #include <intrins.h> #define DPORT P0 #define uchar unsigned char sbit RS = P2^5; sbit RW = P2^6; sbit E = P2^7; uchar Xpos; //列方向地址指針 uchar Ypos; //行方向地址指針 #define NoDisp 0 #define NoCur 1 #define CurNoFlash 2 #define CurFlash 3 /*延時(shí)程序 由Delay參數(shù)確定延遲時(shí)間 */
void LcdWcn(uchar); void LcdWc(uchar); void WriteChar(uchar); void LcdPos(); void LcdWd(uchar); void LcdWdn(uchar); void mDelay(unsigned int Delay) { unsigned int i; for(;Delay>0;Delay--) { for(i=0;i<124;i++) {;} } }
/*光標(biāo)設(shè)置命令 Cur 為設(shè)定光標(biāo)參數(shù) */ void SetCur(uchar Cur) { switch(Cur) { case 0x0: { LcdWc(0x08); //關(guān)顯示 break; } case 0x1: { LcdWc(0x0c); //開(kāi)顯示但無(wú)光標(biāo) break; } case 0x2: { LcdWc(0x0e); //開(kāi)顯示有光標(biāo)但不閃爍 break; } case 0x3: { LcdWc(0x0f); //開(kāi)顯示有光標(biāo)且閃爍 break; } default: break; } } /*清屏命令 */ void ClrLcd() { LcdWc(0x01); } /*在指定的行與列顯示 */ void WriteChar(uchar c) { LcdPos(); LcdWd(c); } /*正常讀寫(xiě)操作之前檢測(cè)LCD控制器 */ void WaitIdle() { uchar tmp; DPORT=0xff; RS=0; RW=1; E=1; _nop_(); for(;;) { tmp=DPORT; tmp&=0x80; if(tmp==0) break; } E=0; } /*不檢測(cè)忙的寫(xiě)字符子程序 */ void LcdWdn(uchar c) { RS=1; RW=0; DPORT=c; //寫(xiě)入待寫(xiě)字符 E=1; _nop_(); E=0; } /*帶忙檢測(cè)的寫(xiě)字符子程序 */ void LcdWd(uchar c) { WaitIdle(); LcdWdn(c); } /*檢測(cè)忙信號(hào)的送控制字子程序*/ void LcdWcn(uchar c) { RS=0; RW=0; DPORT=c; E=1; _nop_(); E=0; } /*檢測(cè)忙信號(hào)的送控制字子程序*/ void LcdWc(uchar c) { WaitIdle(); LcdWcn(c); } void LcdPos() { uchar tmp; Xpos&=0x0f; //16xx型液晶的范圍是0~15 Ypos&=0x01; //Y的范圍是0~1 tmp=Xpos; if(Ypos==1) { tmp+=0x40; } tmp|=0x80; LcdWc(tmp); } /*LCD的復(fù)位程序 */ void RstLcd() { mDelay(15); //延時(shí)15ms LcdWcn(0x38); mDelay(5); LcdWcn(0x38); mDelay(5); LcdWcn(0x38); LcdWc(0x38); LcdWc(0x08); LcdWc(0x01); LcdWc(0x06); LcdWc(0x0c); } void WriteString(char s[]) { uchar pS=0; for(;;) { WriteChar(s[pS]); pS++; if(s[pS]==0) break; if(++Xpos>=15) //每行最多顯示16個(gè)字符 break; } } void main() { uchar s1[]="Hellow World!"; RstLcd(); //復(fù)位LCD ClrLcd(); SetCur(CurFlash); //光標(biāo)顯示且閃爍 Xpos=2; Ypos=1; WriteString(s1); for(;;) {;} } 程序分析:本程序中大量使用了函數(shù),在此對(duì)函數(shù)的功能作一個(gè)簡(jiǎn)介。 C語(yǔ)言程序是由一個(gè)個(gè)函數(shù)構(gòu)成的,從函數(shù)定義的形式上劃分,函數(shù)有三種形式:無(wú)參數(shù)函數(shù)、有參數(shù)函和空函數(shù)。 無(wú)參數(shù)函數(shù)的定義形式為: 返回值類(lèi)型識(shí)別符 函數(shù)名(){函數(shù)體語(yǔ)句} 如本例中的void WaitIdle(){ …… }就是一個(gè)無(wú)參數(shù)函數(shù) 有參數(shù)函數(shù)的定義形式為: 返回值類(lèi)型識(shí)別符 函數(shù)名(形式參數(shù)列表){函數(shù)體語(yǔ)句} 如本例中的void LcdWdn(uchar c){ …… }就是一個(gè)有參數(shù)的函數(shù) 函數(shù)可以返回一個(gè)值,也可以什么值也返回,如果函數(shù)要返回一個(gè)值,在定義這個(gè)函數(shù)時(shí)要定義好這個(gè)值的數(shù)據(jù)類(lèi)型,這里所說(shuō)的數(shù)據(jù)類(lèi)型就是指前面課程中介紹到的int、char、float等類(lèi)型,如果在定義函數(shù)時(shí)沒(méi)有定義返回值的類(lèi)型,系統(tǒng)默認(rèn)為返回一個(gè)int型的值。如果明確地知道一個(gè)函數(shù)將沒(méi)有返回值,可以將其定義為void型,這樣,如果在調(diào)用函數(shù)時(shí)錯(cuò)誤地使用了“變量名=函數(shù)名”的方式來(lái)調(diào)用函數(shù),編譯器就能發(fā)現(xiàn)這一錯(cuò)誤并指出。本例中就大量地應(yīng)用到了void型函數(shù)。 C語(yǔ)言采用函數(shù)之間的參數(shù)傳遞方式,這使得一個(gè)函數(shù)能對(duì)不同的變量進(jìn)行功能相同的處理,使函數(shù)具有了通用性。定義函數(shù)時(shí),寫(xiě)在函數(shù)名括號(hào)中的稱(chēng)之為形式參數(shù),而在實(shí)際調(diào)用函數(shù)時(shí)寫(xiě)在函數(shù)括號(hào)中的稱(chēng)之為實(shí)際參數(shù)。本例中: void SetCur(uchar Cur) { …} 函數(shù)中Cur就是一個(gè)形式參數(shù),而在主函數(shù)中調(diào)用時(shí)寫(xiě)的: SetCur(CurFlash); 其中CurFlash就是一個(gè)用符號(hào)常量表示的實(shí)際參數(shù),在執(zhí)行該函數(shù)時(shí)該值被傳遞到函數(shù)內(nèi)部并執(zhí)行。 每一個(gè)函數(shù)所調(diào)用的函數(shù)必須已被定義,否則就會(huì)出現(xiàn)語(yǔ)法錯(cuò)誤,因此程序中一般要求在程序的開(kāi)頭對(duì)程序中用到的函數(shù)進(jìn)行統(tǒng)一的說(shuō)明,然后再分別定義有關(guān)函數(shù),本例中有: void WriteChar(uchar); … void LcdWdn(uchar); 就是首先在程序的前方寫(xiě)一個(gè)有關(guān)函數(shù)的說(shuō)明,而真正的函數(shù)定義則在程序放在后部。但細(xì)心的讀者可能發(fā)現(xiàn)有一些函數(shù)并未寫(xiě)其說(shuō)明,而是直接在程序中定義了,如mDelay函數(shù),這是為何呢?這是因?yàn)檫@些函數(shù)出現(xiàn)在程序的前面,在還沒(méi)有任何函數(shù)調(diào)用它們之前它們就被定義了,因此就不需要再單獨(dú)寫(xiě)一個(gè)函數(shù)說(shuō)明。讀者可將mDelay函數(shù)的定義移到程序的后面位置,再次編譯就會(huì)出錯(cuò)。當(dāng)然,好的編程習(xí)慣是不論函數(shù)在何處被定義,總是在寫(xiě)前面寫(xiě)一個(gè)函數(shù)說(shuō)明。 有關(guān)單片機(jī)的C語(yǔ)言編程到此就告一個(gè)段落,雖然C語(yǔ)言很多特性尚未介紹,但通過(guò)上面有關(guān)內(nèi)容的學(xué)習(xí),我們已經(jīng)可以使用C語(yǔ)言進(jìn)行一些實(shí)際的工程開(kāi)發(fā)工作,大家可以在工作中繼續(xù)學(xué)習(xí)有關(guān)C語(yǔ)言的知識(shí)。
|