《MCS-51單片機(jī)原理及嵌入式系統(tǒng)應(yīng)用》課件第7章_第1頁
《MCS-51單片機(jī)原理及嵌入式系統(tǒng)應(yīng)用》課件第7章_第2頁
《MCS-51單片機(jī)原理及嵌入式系統(tǒng)應(yīng)用》課件第7章_第3頁
《MCS-51單片機(jī)原理及嵌入式系統(tǒng)應(yīng)用》課件第7章_第4頁
《MCS-51單片機(jī)原理及嵌入式系統(tǒng)應(yīng)用》課件第7章_第5頁
已閱讀5頁,還剩243頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第7章MCS-51系列單片機(jī)與鍵盤、顯示 器、ADC和DAC的接口設(shè)計7.1MCS-51單片機(jī)系統(tǒng)的鍵盤設(shè)計7.2MCS-51單片機(jī)系統(tǒng)的顯示器接口和編程控制7.3MCS-51單片機(jī)與ADC和DAC的接口習(xí)題七7.1.1非編碼式鍵盤的接口設(shè)計和編程利用MCS-51單片機(jī)實現(xiàn)的最簡單的鍵盤如圖7-1所示。圖中利用8051單片機(jī)的P1口構(gòu)成F1(功能1鍵)、F2(功能2鍵)、F3(功能3鍵)、F4(功能4鍵)、▲(向上翻頁)、▼(向下翻頁)、ENT(確認(rèn))和ESC(取消)等8個按鍵。7.1MCS-51單片機(jī)系統(tǒng)的鍵盤設(shè)計圖7-1利用P1口構(gòu)成8個按鍵的電路圖7-1中P1口的8個位作為按鍵使用時,它們都作為輸入口,識別這些按鍵的軟件非常簡單,P1口的各個位狀態(tài)代表各按鍵的狀態(tài)。按照圖7-1這樣利用n位輸入端口構(gòu)成的n個鍵的原理稱為“獨立式”按鍵結(jié)構(gòu)。識別按鍵的程序如下:#define

F1_Key

0x01

//定義常量表示鍵盤碼#define

F2_Key

0x02#define

F3_Key

0x03#define

F4_Key

0x04#define

UP_Key

0x05

//向上翻頁鍵的鍵值=5#define

DOWN_Key

0x06 //向下翻頁鍵的鍵值=6#define

ENT_Key

0x07

//確認(rèn)鍵的鍵值=7#define

ESC_Key

0x08

//取消鍵的鍵值=8unsignedcharGetKeyPadCode(void){

unsignedcharkey;

key=P1;

if(P1==0xFF)

//判斷P1口的8個位是否全為“1”,如果全為“1”表示無按鍵

return0xF0;

//如果沒有鍵按下,則返回0XF0

switch(key)

{

case0xFE:key=F1_Key;

break; //返回F1鍵的鍵值

case0xFD:key=F2_Key;

break; //返回F2鍵的鍵值

case0xFB:key=F3_Key;

break; //返回F3鍵的鍵值

case0xF7:key=F4_Key;

break; //返回F4鍵的鍵值

case0xEF:key=UP_Key;

break; //返回向上翻頁鍵的鍵值

case0xDF:key=DOWN_Key;break; //返回向下翻頁鍵的鍵值

case0xBF:key=ENT_Key;break;//返回確認(rèn)鍵的鍵值

case0x7F:key=ESC_Key;break;//返回取消鍵的鍵值

default:key=0xF0;break;

}

return(key);}上面的程序根據(jù)P1口的8個位中低電平的位置識別被按下的鍵,然后返回相應(yīng)的鍵碼。程序比較簡單,得到整個鍵碼的執(zhí)行過程大約需要幾十微秒。但是,按鍵被按下是一個機(jī)械觸點的接觸(閉合)過程,按鍵被釋放是一個機(jī)械觸點的斷開過程,在這兩個機(jī)械觸點動作過程中會出現(xiàn)機(jī)械觸點抖動,觸點的機(jī)械抖動期間會造成P1口相應(yīng)的位出現(xiàn)電平抖動(即不穩(wěn)定電平),如圖7-2所示。另外,由于外界的振動也可能造成系統(tǒng)按鍵的觸點誤動作。由于觸點的機(jī)械特性造成的電平抖動時間一般為5~10ms,如果在此期間連續(xù)快速掃描鍵碼,容易使CPU錯誤響應(yīng)按鍵。圖7-2按鍵被按下和釋放時的電平抖動示意圖為了保證單片機(jī)能夠正確處理和響應(yīng)鍵盤,保證鍵穩(wěn)定閉合一次,單片機(jī)只響應(yīng)一次,系統(tǒng)對鍵盤的掃描過程必須有過濾電平抖動的處理程序。由于機(jī)械觸點的抖動時間大約在10ms以內(nèi),簡單的“去抖動”處理就是連續(xù)讀鍵盤至少兩次,每次間隔大于20ms。如果連續(xù)兩次得到的鍵碼是相同的,那么表示按鍵的狀態(tài)(按下狀態(tài)或釋放狀態(tài))是穩(wěn)定的,然后CPU就可以響應(yīng)按鍵的動作。采用查詢等待方式掃描鍵盤的程序如下:unsignedcharidataNowKeyCode=0;

//定義一個全局變量存儲當(dāng)前的按鍵unsignedcharScanKeyPad(void)

//掃描鍵盤程序,有鍵按下時返回1,否則返回0{

unsignedchark1,k2;

do{ //循環(huán)掃描鍵碼,直至連續(xù)兩次得到相同的鍵碼

k1=GetKeyPadCode();

//調(diào)讀鍵碼的函數(shù),將返回的鍵碼暫存在變量k1中

if(k1==0xFF)

//判斷是否有鍵按下

if(k1==0xFF)

//判斷是否有鍵按下

return0;

//如果沒有按鍵動作,返回0

Delay(200);

//延時20ms

k2=GetKeyPadCode();

//調(diào)讀鍵碼的函數(shù),將返回的鍵碼暫存在變量k2中

if(k2==0xFF)

//判斷是否有鍵按下

return0;

//如果沒有按鍵動作,返回0

}while(k1!=k2);

//如果連續(xù)兩次得到的鍵碼不相同,繼續(xù)掃描鍵碼

NowKeyCode=k1;

//保存當(dāng)前被按下鍵的鍵碼在變量NowKeyCode中

return1;

//有鍵被按下,返回1,鍵碼保存在變量NowKeyCode中

}采用這種查詢等待方式掃描鍵盤的程序在嵌入式實時控制系統(tǒng)中是非常不合理的,當(dāng)有鍵被按下或釋放時,系統(tǒng)CPU執(zhí)行上面的ScanKeyPad()子程序至少需要20ms的時間,在此期間其他任務(wù)都被迫終止(除了中斷服務(wù)程序外),造成嵌入式實時系統(tǒng)的實時性降低。為了不影響系統(tǒng)的實時性,CPU對鍵盤處理可以采用定時掃描方式,由MCS-51單片機(jī)內(nèi)部的定時器產(chǎn)生定時中斷,定時喚醒CPU掃描鍵盤。下面的程序是采用定時器0定時20ms,產(chǎn)生20ms定時中斷,當(dāng)定時器溢出時,主程序得到T0中斷服務(wù)程序發(fā)來的Over20ms的消息,然后進(jìn)入鍵盤掃描任務(wù)。unsignedcharidataOver20ms;

//全局變量,T0溢出標(biāo)志unsignedcharidataNowKeyCode,OldKeyCode;

//KeyPadTask()必需的全局變量unsignedcharidataKeyPadWatCnt;

//KeyPadTask()必需的全局變量voidInit_8051(void){

EA=0;

//初始化T0之前關(guān)閉中斷

TR0=0;

//T0定時器停止工作

TMOD=0x01;

//設(shè)置T0工作模式為定時器,工作方式為方式1

TL0=0xDF;

//fosc=12MHz,要求定時20ms

TH0=0xB1;

//裝入T0定時器初始值

IE=0x82;

//允許T0和T1中斷請求

Over20ms=0; //將“20ms定時時間到”的標(biāo)志清零

TR0=1;

//啟動T0開始定時

EA=1;

//中斷總使能位置位

//其他初始化程序}interrupt[0x0B]voidT0_ISR(void) //T0中斷服務(wù)程序{

TL0=0xDF;

//fosc=12MHz,要求定時20ms

TH0=0xB1;

//重新裝入T0定時器初始值

Over20ms=1; //20ms定時時間到,向主程序發(fā)送標(biāo)志}voidmain(void){

Init_8051();

//初始化程序

while(1)

{

//實時系統(tǒng)的任務(wù)之一是處理鍵盤任務(wù)

if(Over20ms)

//判斷是否有T0中斷的標(biāo)志

{

//當(dāng)收到T0中斷的標(biāo)志,處理鍵盤

Over20ms=0;

//將T0中斷服務(wù)程序發(fā)送來的標(biāo)志清零

KeyPadTask(); //處理鍵盤任務(wù)

}

//othertaskrunninghere //實時系統(tǒng)的其他任務(wù)的執(zhí)行和響應(yīng)

}}voidKeyPadTask(void)

//處理鍵盤任務(wù){(diào)

unsignedcharnowk;

nowk=GetKeyPadCode();

if(nowk==0xF0)

//判斷是否有按鍵

{

//當(dāng)前沒有任何鍵被按下時,將各變量還原

KeyPadWatCnt=0;

//鍵盤“去抖動”計數(shù)器清零

OldKeyCode=0;

//保存前一次鍵碼的變量清零

NowKeyCode=0;

//存儲“已經(jīng)響應(yīng)過的按鍵”變量清零

return;

//沒有按鍵被按下,直接返回

}

if(OldKeyCode!=nowk)

//判斷是否是新的按鍵

{

OldKeyCode=nowk; //保存新的鍵碼在變量OldKeyCode中

KeyPadWatCnt=0; //鍵盤“去抖動”計數(shù)器清零

return;

//保存新的鍵碼后直接返回

}

//本次得到的鍵碼與前一次的鍵碼相同,繼續(xù)向下運(yùn)行

if((KeyPadWatCnt++)>0x02)

//判斷是否已經(jīng)有連續(xù)兩次相同的鍵碼

{

if(NowKeyCode==OldKeyCode)

//判斷當(dāng)前的按鍵是否已經(jīng)被響應(yīng)

return;

//當(dāng)前的按鍵已經(jīng)被響應(yīng),就不能響應(yīng)兩次

NowKeyCode=OldKeyCode;

//有連續(xù)兩次相同的鍵碼,說明有鍵被穩(wěn)定按下, 將被響應(yīng)的按鍵保存在NowKeyCode變量中

//KeyPadProFun(); //處理、響應(yīng)未響應(yīng)的按鍵動作

}}按照上面程序的執(zhí)行過程,MCS-51單片機(jī)每隔20ms執(zhí)行一次鍵盤任務(wù)(執(zhí)行一次KeyPadTask()子程序)。如果沒有按鍵動作,執(zhí)行過程僅需要幾微秒時間;當(dāng)有鍵被按下或釋放時,不考慮鍵盤響應(yīng)(執(zhí)行KeyPadProFun()子程序)的時間,僅需要大約幾十微秒的時間。這比前面以“查詢等待方式”實現(xiàn)的程序的執(zhí)行速度提高了1000倍左右,在實時性要求比較高的應(yīng)用系統(tǒng)中,定時掃描方式實現(xiàn)處理鍵盤的程序更合理。利用MCS-51單片機(jī)的I/O端口擴(kuò)展獨立式按鍵在按鍵個數(shù)較少的系統(tǒng)中可以使用。如果系統(tǒng)需要按鍵的個數(shù)比較多,則這種方式需要占用系統(tǒng)大量的I/O端口,非常浪費(fèi)系統(tǒng)的資源。當(dāng)系統(tǒng)需要按鍵的個數(shù)比較多時采用行列式矩陣結(jié)構(gòu)的鍵盤更合理,即利用MCS-51系列單片機(jī)的I/O端口相互交叉形成的行列式鍵盤,這種方法不僅節(jié)省I/O端口,而且鍵盤掃描和鍵盤識別的軟件也比較簡單。圖7-3是采用行列式方法,利用8051的P1口構(gòu)成16個按鍵的電路。這個4×4的行列式鍵盤的行線是P1.0~P1.3,列線是P1.4~P1.7,形成4×4=16個交叉點,每個交叉點連接一個按鍵。16個按鍵分別為:數(shù)字鍵“1”(P1.0與P1.7的交叉點)、數(shù)字鍵“2”(P1.0與P1.6的交叉點)、數(shù)字鍵“3”(P1.0與P1.5的交叉點)、功能鍵“Fn”(P1.0與P1.4的交叉點)、數(shù)字鍵“4”(P1.1與P1.7的交叉點)、數(shù)字鍵“5”(P1.1與P1.6的交叉點)、數(shù)字鍵“6”(P1.1與P1.5的交叉點)、向上翻頁鍵“▲”(P1.1與P1.4的交叉點)、數(shù)字鍵“7”(P1.2與P1.7的交叉點)、數(shù)字鍵“8”(P1.2與P1.6的交叉點)、數(shù)字鍵“9”(P1.2與P1.5的交叉點)、向下翻頁鍵“▼”(P1.2與P1.4的交叉點)、“CLR”(P1.3與P1.7的交叉點)、數(shù)字鍵“0”(P1.3與P1.6的交叉點)、“ESC”(P1.3與P1.5的交叉點)、“ENT”(P1.3與P1.4的交叉點)。當(dāng)沒有任何鍵按下時,所有的交叉點都是斷開的,由于列線的上拉電阻作用,使其保持高電平。如果行線P1.0~P1.3被軟件設(shè)置為低電平,當(dāng)有任何按鍵被按下時,該鍵所在的行線和列線被按鍵短路,那么相應(yīng)的列線就變?yōu)榈碗娖健D7-3利用P1口構(gòu)成16個按鍵的電路行列式結(jié)構(gòu)鍵盤的鍵碼識別過程如下:MCS-51單片機(jī)軟件首先設(shè)置P1.0~P1.3(行線)都輸出低電平,列線P1.4~P1.7為輸入端口,讀列線的狀態(tài)并判斷。如果列線都為高電平,說明沒有任何交叉點閉合,即沒有任何鍵被按下;如果有任何列線為低電平,說明有鍵被按下,并且根據(jù)低電平列線的位置可以確定被按下的鍵在哪一列。譬如數(shù)字鍵“0”被按下,低電平的列線是P1.6,軟件根據(jù)P1.6為低電平這個條件可以準(zhǔn)確地確定被按下的鍵肯定是數(shù)字鍵“2”、“5”、“8”和“0”4個鍵中的某一個,但是具體是哪一個鍵還不能確定,需要利用行線掃描查找鍵的準(zhǔn)確位置。保存低電平列線的位置后,軟件將行線全部設(shè)置為高電平,然后僅將第一行線P1.0置為低電平,判斷P1.6(前面確定的低電平的列線位置)是否為低電平,由于P1.0和P1.6的交叉點并未閉合,因而此時P1.6為高電平,軟件可以確定不是數(shù)字鍵“2”;需要繼續(xù)查找,將行線P1.0置為高電平,并且將第二行線P1.1置為低電平,然后判斷P1.6的電平狀態(tài),如此重復(fù),直到對應(yīng)行線為低電平時,列線P1.6也為低電平,它們的交叉點就是被按下的鍵的位置。當(dāng)使用n個雙向I/O端口構(gòu)成行列式鍵盤時,鍵的個數(shù)可以利用下面的式子確定:

n為偶數(shù)n個雙向I/O端口構(gòu)成的按鍵個數(shù)=

n為奇數(shù)當(dāng)n=8時,構(gòu)成的按鍵個數(shù)為16個;當(dāng)n=16時,構(gòu)成的按鍵個數(shù)為64個。下面的程序是識別4×4的行列式鍵盤的程序:#define

Numeric0Key

0x0

//定義常數(shù)表示相應(yīng)的鍵碼#define

Numeric1Key

0x01#define

Numeric2Key

0x02#define

Numeric3Key

0x03#define

Numeric4Key

0x04#define

Numeric5Key

0x05#define

Numeric6Key

0x06#define

Numeric7Key

0x07#define

Numeric8Key

0x08#define

Numeric9Key

0x09#define

CLRKey

0x0A#define

FnKey

0x0B#define

PageUpKey

0x0C#define

PageDownKey

0x0D#define

ESCKey

0x0E#define

ENTKey

0x0F

//所有正常鍵碼的高4位都為“0”codeunsignedcharKeyPadPositionTable[]={

0xB7,0x7E,0xBE,0xDE,0x7D,0xBD,0xDD,0x7B,0xBB,0xDB,

//數(shù)字鍵“0”~“9”

0x7E,0xEE,0xED,0xEB,0xD7,0xE7

//CLR、Fn、▲、▼、ESC、ENT鍵}unsignedcharGetKeyPadCode(void)

//識別4×4的行列式鍵盤的鍵碼的子程序{

//如果無鍵,返回0xF0;否則返回鍵碼

unsignedcharkey,column,line,i;

key=P1;

P1=key&0xF0;

//設(shè)置P1.0~P1.3(行線)為低電平

for(key=4;key>0;key--);

//延時4微秒,等待輸出電平狀態(tài)穩(wěn)定

key=P1;

//讀P1.4~P1.7(列線)的狀態(tài)

if((key&0xF0)==0xF0)

//判斷是否有列線為低電平

return(0xF0);

//如果所有列線都為高電平,即無任何鍵被按下,則返回

column=key&0xF0;

//保存列線的狀態(tài)在變量column中

line=0xFE;

//首先置P1.0為低電平

for(i=0;i<4;i++)

//行線被逐個置低電平,確定鍵的位置

{

P1=line;

//將惟一的低電平信號寫到P1口

for(key=2;key>0;key--);

//延時2微秒,等待輸出電平狀態(tài)穩(wěn)定

key=P1;

if((key&0xF0)==column)

//比較低電平的列線

break;

//被按下的鍵位置被確定,終止循環(huán)

line<<=1;

//低電平的位置左移一位

}

P1=0xF0;

//重新將所有的行線置為低電平狀態(tài)

if(i==4)

return(0xF0);

//查找按鍵的位置操作失敗,認(rèn)為沒有按鍵,返回

key=line&column;

//合并行線和列線的狀態(tài),其中高低4位各有一個“0”

for(i=0;i<16;i++)

//根據(jù)行列交叉點在鍵盤位置表中快速查找位置

if(key==KeyPadPositionTable[i])

break;

//如果找到,終止查找

if(i!=16)

returni;

//已經(jīng)找到鍵的位置和鍵碼,返回鍵碼

return(0xF0);

//在表中未找到響應(yīng)的鍵位置,認(rèn)為沒有鍵

}比較獨立式鍵盤的讀取鍵碼子程序GetKeyPadCode()和4×4的行列式鍵盤的讀取鍵碼子程序GetKeyPadCode(),MCS-51單片機(jī)執(zhí)行兩個子程序的時間有較大差異,后者大約是前者的5倍,后者估計需要0.1ms左右。顯然,實現(xiàn)相同個數(shù)的按鍵時,獨立式鍵盤的鍵碼識別速度較快,但是需要占用較多的I/O端口;行列式鍵盤的鍵碼識別速度相對較慢,但是能夠有效地節(jié)省I/O端口的資源。圖7-3中擴(kuò)展的鍵盤允許應(yīng)用程序以中斷方式處理和響應(yīng)鍵盤,所有的行線都保持低電平狀態(tài),一旦有任何按鍵被按下時,INT0引腳處會出現(xiàn)低電平的中斷請求信號,在INT0中斷服務(wù)程序中向主程序發(fā)送“有按鍵動作”的消息(標(biāo)志)。當(dāng)主程序收到該消息時,才運(yùn)行鍵盤處理和響應(yīng)的任務(wù),CPU在沒有按鍵的時間中可以處理和響應(yīng)其他任務(wù)。這種方法比較適合嵌入式實時控制系統(tǒng)軟件對行列式鍵盤的處理。7.1.2其他方式的鍵盤接口在上一節(jié)中利用MCS-51系列單片機(jī)的P1口擴(kuò)展獨立式鍵盤和行列式鍵盤是比較常用的非編碼式鍵盤接口設(shè)計,但是,P1口是支持位操作的雙向I/O端口,是MCS-51單片機(jī)的寶貴資源,往往更希望把它們作為擴(kuò)展串行接口的器件的I/O線使用。為MCS-51單片機(jī)系統(tǒng)擴(kuò)展鍵盤還有其他方法,如利用第六章中提到的“擴(kuò)展的外部I/O通道”構(gòu)成行列式開關(guān)矩陣,是利用外部擴(kuò)展資源實現(xiàn)行列式鍵盤的方法之一。這種行列式鍵盤與前面講到的行列式鍵盤的鍵碼識別原理相同,無非是P1口和兩個外部I/O通道(一個是只讀的三態(tài)緩沖門,另一個是只寫的鎖存器)之間的訪問方式不同而已。圖7-4是利用MCS-51單片機(jī)擴(kuò)展的I/O通道實現(xiàn)16個按鍵的電路,電路中擴(kuò)展了一個8位的三態(tài)緩沖門(U2)74HC244和一個8位D型鎖存器(U3)74HC374,其中三態(tài)緩沖門的低4位作為輸入口使用,是4×4鍵盤的4根列線;鎖存器的低4位作為輸出口使用,是鍵盤的4根行線。這個電路的鍵碼識別方法與前一節(jié)中的4×4行列式鍵盤相同。圖7-4利用擴(kuò)展的I/O通道構(gòu)成16個按鍵的電路另外,也可以利用專用的鍵盤/顯示器接口芯片——Intel公司的8279實現(xiàn)鍵盤的接口。它屬于一種專用編碼式鍵盤芯片,是Intel公司提供的通用鍵盤/顯示器接口芯片。利用8279可以實現(xiàn)對鍵盤和動態(tài)掃描LED顯示器的自動掃描,自動識別鍵盤的鍵碼。在MCS-51系列單片機(jī)系統(tǒng)中擴(kuò)展8279芯片實現(xiàn)鍵盤和LED顯示器,不僅可以大大節(jié)省單片機(jī)對鍵盤和顯示器的操作時間,從而減輕單片機(jī)執(zhí)行程序的負(fù)荷,提高嵌入式實時系統(tǒng)的實時性,而且控制程序簡單,顯示穩(wěn)定,不會出現(xiàn)誤動作。

PDIP封裝的8279芯片一共有40個引腳,其內(nèi)部包括鍵盤輸入控制邏輯塊、I/O控制和數(shù)據(jù)緩沖塊、掃描計數(shù)器、接口和譯碼控制邏輯、FIFORAM(FirstInFirstOutRAM)隊列等。8279提供4根鍵盤和顯示器的掃描輸出線及8根鍵盤狀態(tài)反饋線,利用它們可以直接構(gòu)成4×8=32個鍵的行列式鍵盤。有關(guān)Intel8279的詳細(xì)說明和接口設(shè)計、編程方法等請參考相關(guān)資料。隨著CPLD和FPGA技術(shù)的迅速發(fā)展,以“單片機(jī)+CPLD/FPGA”為核心設(shè)計、實現(xiàn)的嵌入式控制系統(tǒng)越來越多,將傳統(tǒng)的單片機(jī)外圍器件(除了大容量存儲器外)絕大多數(shù)都可以集成在一片CPLD/FPGA內(nèi)部,即使是一個功能強(qiáng)大、復(fù)雜的單片機(jī)系統(tǒng)也都是“單片機(jī)+CPLD/FPGA”的2片結(jié)構(gòu),這種方法既能夠發(fā)揮CPLD和FPGA的靈活性,而且開發(fā)的系統(tǒng)可以適用于多種目的,系統(tǒng)的結(jié)構(gòu)比較簡單,可靠性得以提高。8279作為一種傳統(tǒng)的鍵盤和顯示器專用接口芯片,其功能完全可以集成到CPLD/FPGA內(nèi)部,而不需要專門擴(kuò)展這些接口芯片。常用的編碼式專用鍵盤接口擴(kuò)展芯片還有74HC922和74HC923,它們是屬于74系列的專用集成電路。74HC922提供行線X1~X4和列線Y1~Y4,并且都具有內(nèi)部上拉電阻,利用行線和列線可以直接構(gòu)成4×4=16個鍵的行列式鍵盤;74HC923具有4根行線和5根列線,可以構(gòu)成4×5=20個鍵的行列式鍵盤。74HC922采用4位并行三態(tài)數(shù)據(jù)總線輸出鍵碼,可以與MC-51系列單片機(jī)的數(shù)據(jù)總線直接連接,并且具有“有按鍵和鍵碼”的標(biāo)志信號(或握手信號線)。74HC923則采用5位并行三態(tài)數(shù)據(jù)總線輸出鍵碼。

74HC922與74HC923的引腳排列(PDIP封裝)和名稱如圖7-5所示。表7-1列出了74HC923的引腳名稱和功能。圖7-574HC922/3鍵盤編碼器引腳排列和名稱與其他專用的鍵盤編碼器芯片相比,74HC922和74HC923都屬于低成本的鍵盤接口擴(kuò)展芯片,它們具有功能單一、接口簡單、使用操作簡單等優(yōu)點。它們在MCS-51單片機(jī)系統(tǒng)使用時,器件的外部僅需要兩個電容,一個是掃描時鐘振蕩器電容,另一個是鍵盤“去抖動”電容。器件的三態(tài)數(shù)據(jù)輸出總線可以與MCS-51系列單片機(jī)的數(shù)據(jù)總線直接連接,僅占用單片機(jī)的一個I/O擴(kuò)展地址資源,MCS-51單片機(jī)執(zhí)行外部讀操作就可以將鍵碼讀入CPU內(nèi)部寄存器。74HC922和74HC923都帶有DataValid信號輸出,當(dāng)有且僅有一個鍵被按下而且觸點穩(wěn)定閉合時,該信號輸出一個有效的低電平脈沖,可以和MCS-51單片機(jī)的外部中斷輸入引腳INT0或INT1連接,實現(xiàn)中斷方式處理和響應(yīng)鍵盤。圖7-6是利用74HC922擴(kuò)展4×4結(jié)構(gòu)的行列式鍵盤電路。圖7-6利用74HC922擴(kuò)展4×4結(jié)構(gòu)行列式鍵盤電路程序使用INT0中斷方式處理和響應(yīng)鍵盤,當(dāng)有鍵被按下時,DAV輸出有效信號向8051單片機(jī)申請中斷。在8051的INT0中斷服務(wù)程序中,首先從74HC922中將鍵碼讀出存放在變量CurrentKeyCode中,并且在讀鍵碼的同時將中斷請求信號復(fù)位,得到正確的鍵碼后,INT0中斷服務(wù)程序置HaveKeyActive標(biāo)志有效,向主程序發(fā)送消息,鍵盤的響應(yīng)和處理在主程序中完成。#include<io51.h>#define

KeyPortAdr*(unsignedchar*)(0x010000)

//74HC922的地址unsignedcharidataCurrentKeyCode,HaveKeyActive=0;interrupt[0x03]voidINT0_ISR(void){

CurrentKeyCode=KeyPortAdr;

//將鍵碼讀到變量CurrentKeyCode中

CurrentKeyCode&=0x0F;

//僅低4位有效,所以屏蔽高4位

HaveKeyActive=1; //有按鍵被按下,向主程序發(fā)送消息}…voidmain(void){

//初始化程序,包括中斷INT0的初始化

while(1){

if(HaveKeyActive) //檢查是否有中斷INT0的消息

{

HaveKeyActive=0;

//標(biāo)志被清除

//KeyPadProFun();

//處理、響應(yīng)按鍵動作

}

//其他任務(wù)

}}7.2MCS-51單片機(jī)系統(tǒng)的顯示器接口和編程控制在以MCS-51單片機(jī)為核心的嵌入式控制系統(tǒng)中常用的顯示器包括段式LED(LightEmittingDiode,發(fā)光二極管)顯示器、點陣LED顯示器、段式LCD(LiquidCrystalDisplay,液晶顯示器)、字符型LCD、圖形點陣LCD、段式VFD(VacuumFluorescentDisplay,真空熒光顯示器)、字符型VFD、圖形點陣VFD等。所有的LED顯示器都是將多個發(fā)光二極管組合而成。段式LED顯示器應(yīng)用最廣泛,它是一種低成本、高可靠性、高穩(wěn)定性的顯示器,而且亮度也比較高,使用壽命長;點陣LED顯示器作為戶外文字廣告和信息牌被廣泛使用。LED顯示器的缺點是消耗功率大,容易發(fā)熱,體積相對較大。

LCD顯示器具有功耗低、體積小等優(yōu)點,它們被廣泛使用于各種手持設(shè)備、智能終端設(shè)備,目前LCD顯示器作為一種綠色平板顯示器已經(jīng)逐步成為PC的主流顯示終端。段式LCD可以適用于各類數(shù)字型儀表;字符型LCD能夠顯示ASCII字符和簡單的圖形,在各種嵌入式系統(tǒng)中被廣泛使用;圖形點陣LCD能夠顯示各種圖形、曲線和漢字,在高檔儀器和嵌入式終端中被廣泛使用。LCD顯示器必須采用交流掃描信號,缺點是容易被干擾,而且使用壽命相對較短。

VFD顯示器具有亮度高、穩(wěn)定性高、壽命長等優(yōu)點,但是所有的VFD器件都必須使用高壓驅(qū)動電路,而且它們消耗的電流較大。VFD顯示器應(yīng)用最頻繁的領(lǐng)域是家用電器。7.2.1LED顯示器的接口所有的LED顯示器件都是由若干LED組合而成的,當(dāng)某一個LED導(dǎo)通時,該LED表示的點或段(筆畫)被點亮,單片機(jī)控制多個不同的點或段的亮或滅,可以顯示出不同的數(shù)碼或字符。常用段式LED顯示器包括“七段”結(jié)構(gòu)LED顯示器和“米字”結(jié)構(gòu)LED顯示器。它們都有共陰極和共陽極兩種結(jié)構(gòu),其中共陰極LED顯示器內(nèi)部所有發(fā)光二極管的陰極連接在一起,而所有發(fā)光二極管的陽極各自獨立;共陽極LED顯示器內(nèi)部發(fā)光二極管的陽極連接在一起,而所有發(fā)光二極管的陰極各自獨立。圖7-7是“七段”結(jié)構(gòu)的段式LED顯示器的內(nèi)部結(jié)構(gòu)和外型、引腳的示意圖,其中“dp”段是小數(shù)點指示段?!懊鬃帧毙徒Y(jié)構(gòu)的LED顯示器的內(nèi)部結(jié)構(gòu)僅比“七段”結(jié)構(gòu)的LED顯示器多了5段,增加的5段從外型上看,是將原來的“g”段改成兩段,并在“8”字中間增加“X”形狀的4段,成為“米”字形狀。圖7-7“七段”結(jié)構(gòu)的LED顯示器的內(nèi)部結(jié)構(gòu)和外型、引腳示意圖(a)共陰極結(jié)構(gòu);(b)共陽極結(jié)構(gòu);(c)外型和引腳排列按照圖7-7中的“七段”結(jié)構(gòu)LED顯示器的外型和段的位置,“七段”LED顯示器顯示碼與控制碼的對照表如表7-2所示。段式LED顯示器的控制方式分為靜態(tài)顯示控制和動態(tài)顯示控制兩種。所謂“靜態(tài)顯示控制”,就是當(dāng)一個LED顯示器顯示某字符時,控制碼控制相應(yīng)的LED段處于恒定的導(dǎo)通狀態(tài),靜態(tài)顯示控制在電路上需要將控制碼鎖存在LED顯示器的各段輸入引腳,如果有多位LED顯示器,每個位必需一個8位鎖存器,MCS-51單片機(jī)僅在需要更改顯示器的顯示內(nèi)容時,才重新將新的控制碼鎖存在8位鎖存器中。靜態(tài)顯示控制的LED顯示器的亮度與各段的導(dǎo)通電流大小有關(guān),靜態(tài)控制的顯示是非常穩(wěn)定的。所謂“動態(tài)顯示控制”,就是多位顯示器逐個掃描,任意時刻僅有某一個顯示器是亮的,而其他各位都不亮,一個位亮一定時間后轉(zhuǎn)向另一個位。這種動態(tài)逐個掃描多位LED顯示器的方式會造成顯示位“閃爍”,但是,適當(dāng)?shù)卣{(diào)整掃描速度,利用人的視覺暫留,使人的眼睛看起來“不閃爍”。動態(tài)掃描LED顯示器方式比靜態(tài)顯示控制方式的電路更簡單,將多位LED顯示器的段引腳對應(yīng)連接成“段”總線,僅需要一個8位鎖存器和多個位選通控制線就可以達(dá)到控制多位LED顯示器的目的。動態(tài)掃描LED顯示器的亮度與各段的導(dǎo)通電流有關(guān),另外,亮度還與掃描頻率(一個位亮的時間和滅的時間稱為一個掃描周期)有關(guān)。圖7-8和圖7-9是利用擴(kuò)展的I/O通道分別實現(xiàn)靜態(tài)LED顯示器和動態(tài)LED顯示器的電路。在圖7-8中為實現(xiàn)3位LED顯示器需要擴(kuò)展3個8位的D型鎖存器74HC273,每個鎖存器的輸出端經(jīng)過限流電阻后與各位LED顯示器的a~dp段對應(yīng)連接。擴(kuò)展的3個鎖存器的地址分別為0DFFFH、0BFFFH和7FFFH,8051單片機(jī)將各位需要顯示的字符對應(yīng)的段控制碼鎖存在各鎖存器中,即可實現(xiàn)顯示器的控制。一旦段控制碼鎖存后,顯示器一直保持顯示的字符,直到8051單片機(jī)重新寫新的段控制碼到鎖存器中。圖7-83位LED顯示器的靜態(tài)控制接口電路在圖7-9中,擴(kuò)展了兩個8位D型鎖存器74HC273,U2作為段控制碼鎖存器使用,U3作為顯示器位選通碼使用,4位LED顯示器的段引腳a~dp對應(yīng)連接構(gòu)成“段”總線與U2的輸入連接。每一個位選通控制線都經(jīng)過一個達(dá)林頓結(jié)構(gòu)的驅(qū)動器(75452),當(dāng)8051單片機(jī)通過寫操作將段控制碼鎖存在段碼鎖存器中,然后控制位選通信號中的某一個位有效,此時該顯示位顯示段碼鎖存器中對應(yīng)的字符。一個顯示位亮一定時間后,8051單片機(jī)將所有的位選通信號都置為無效,然后重新將下一個顯示位的字符的段控制碼鎖存在段碼鎖存器中,再將這個位選通信號置為有效,這樣重復(fù)掃描4個LED顯示器。圖7-94位LED顯示器的動態(tài)控制接口電路比較上面兩個電路,如果需要顯示器的位數(shù)相同,那么靜態(tài)控制方式的電路需要擴(kuò)展更多的鎖存器。相比較而言,動態(tài)控制方式的電路就比較簡單。下面是兩種不同顯示控制方式的控制程序。靜態(tài)顯示控制方式的程序:#include<io51.h>#define

StaticDisplayLED0Adr*(unsignedchar*)(0x01DFFF)

//BIT0地址#define

StaticDisplayLED1Adr*(unsignedchar*)(0x01BFFF)

//BIT1地址#define

StaticDisplayLED2Adr*(unsignedchar*)(0x017FFF)

//BIT2地址codeunsignedcharLEDSegmentCode[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71}unsignedcharidataDisplayBuffer[3];

//顯示緩沖區(qū)…voidStaticLEDDisplayUpdate(void)

//刷新靜態(tài)LED顯示器的子程序{

unsignedcharct;

ct=DisplayBuffer[0]&0x0F;

//僅顯示“0”~“F”

StaticDisplayLED0Adr=LEDSegmentCode[ct];

//將段碼鎖存在BIT0地址

ct=DisplayBuffer[1]&0x0F;

//僅顯示“0”~“F”

StaticDisplayLED1Adr=LEDSegmentCode[ct];

//將段碼鎖存在BIT1地址

ct=DisplayBuffer[2]&0x0F;

//僅顯示“0”~“F”

StaticDisplayLED2Adr=LEDSegmentCode[ct];

//將段碼鎖存在BIT2地址}在下面的動態(tài)顯示方式控制程序中,利用Timer0定時20ms,作為LED顯示器的掃描周期。源程序如下:#include<io51.h>#define

DynamicDispSegCodeAdr*(unsignedchar*)(0x01BFFF)

//段碼鎖存器地址#define

DynamicDispBitSelectAdr*(unsignedchar*)(0x017FFF)

//位選通碼鎖存器地址codeunsignedcharLEDSegmentCode[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};codeunsignedcharLEDBitSelectCode[]={0x01,0x02,0x04,0x08};unsignedcharidataDisplayBuffer[3];

//顯示緩沖區(qū)unsignedcharidataOver20ms=0;

//20ms定時溢出標(biāo)志unsignedcharidataCurrentLEDBitPt=0;//定時掃描LED的位指針interrupt[0x0B]voidTimer0_ISR(void){

TL0=0xDF;

//fosc=12MHz,要求定時20ms

TH0=0xB1;

//重新裝入T0定時器初始值

Over20ms=1;

//20ms定時時間到,向主程序發(fā)送標(biāo)志}voidmain(void)

//主程序{

unsignedncharcct;

//初始化程序

while(1)

//主程序無限循環(huán)開始

{

if(Over20ms) //從Timer0中斷服務(wù)程序接收到消息

{

Over20ms=0;

//清除標(biāo)志

DynamicDispBitSelectAdr=0x00;

//讓所有的位選通線都無效

cct=DisplayBuffer[CurrentLEDBitPt]&0x0F;

//從顯示緩沖區(qū)取顯示數(shù)據(jù)

DynamicDispSegCodeAdr=LEDSegmentCode[cct];

//鎖存段碼

DynamicDispSegCodeAdr=LEDBitSelectCode [CurrentLEDBitPt];

//置指針指向的位的位選通碼有效

CurrentLEDBitPt++;

//顯示器位指針加1

if(CurrentLEDBitPt>4) //判斷顯示器位指針是否已經(jīng)大于4

CurrentLEDBitPt=0;

//當(dāng)大于4時,重新開始下一輪顯示掃描

}

//執(zhí)行系統(tǒng)的其他任務(wù)

}}動態(tài)掃描LED顯示器時,為了防止“串亮”,在每次修改段碼鎖存器中的段控制碼之前,必須首先讓所有的位選通線都無效。比較上面兩種控制程序可以看出,采用靜態(tài)顯示控制方式的LED顯示器刷新程序比較簡單,當(dāng)主程序需要刷新顯示的字符時才將新的段控制碼鎖存一次,平時不需要更改顯示的字符時,靜態(tài)控制方式的LED顯示器能夠自動保持顯示的字符。而對動態(tài)顯示控制方式的LED顯示器來講,無論主程序是否要更改顯示的字符,程序必須周期性地掃描LED顯示器,需要周期性占用CPU的時間去逐位刷新,否則動態(tài)控制方式的LED顯示器將不能正常工作。

MCS-51系列單片機(jī)與LED顯示器的接口方法還有很多種,如利用Intel公司的鍵盤和顯示器專用接口芯片8279(參考前一節(jié)的有關(guān)內(nèi)容)控制LED顯示器,這是一種傳統(tǒng)的擴(kuò)展方法。在MCS-51單片機(jī)系統(tǒng)中擴(kuò)展8279作為鍵盤和LED顯示器接口電路,可以構(gòu)成32個鍵的行列式鍵盤和8位LED顯示器。7.2.2字符型LCD顯示器的接口與LED顯示器相比,LCD顯示器是一種功耗極低的顯示器件。液晶(LiquidCrystal)的特點是在一定的溫度范圍內(nèi)既有液體的流動性和連續(xù)性,又有晶體的各向異性,它們的分子呈現(xiàn)長棒形狀,長和寬的比例較大,分子不能彎曲,是一種剛性體。它們的中心一般有橋鏈,兩頭有極性。

LCD顯示器件的內(nèi)部結(jié)構(gòu)原理如圖7-10所示。由于液晶的“四壁效應(yīng)”,在定向膜的作用下,液晶材料的分子在正、背玻璃板電極上呈水平排列,但排列方向互為正交,而玻璃電極之間的分子呈連續(xù)扭轉(zhuǎn)過渡,這樣的構(gòu)造能使液晶對光產(chǎn)生旋光作用,使光的偏振方向旋轉(zhuǎn)90°。所以說,LCD顯示器屬于非主動發(fā)光的光源,為了能夠看到LCD顯示器中的字符或圖形,必須在光線充足的地方,或為LCD顯示器提供外界主動發(fā)光的光源。為了在夜間能夠使用LCD顯示器,目前絕大多數(shù)LCD顯示器都帶有背光板,LCD顯示器背光板必須能夠為LCD顯示器提供充足的背景光線。LCD顯示器的背光板光源可以選擇各種不同的顏色,可以得到不同的顯示效果。圖7-10LCD的基本構(gòu)造示意圖圖7-11是LCD顯示器的工作原理示意圖。當(dāng)外界主動發(fā)光源的光線通過上偏振片后形成偏振光,偏振方向呈垂直方向。然后,此偏振光通過液晶材料之后被旋轉(zhuǎn)90°,此時光線的偏振方向呈水平,此方向與下偏振片的方向一致,因此此光線能夠穿過下偏振片而到達(dá)反射板。最后,該光線的反射光線沿原路返回,從而使LCD顯示器呈現(xiàn)透明狀。當(dāng)在液晶盒的上、下電極間加上一定電壓后,電極部分的液晶分子轉(zhuǎn)為垂直排列,從而失去旋光性。因此,從上偏振片入射的偏振光不被旋轉(zhuǎn),當(dāng)此偏振光到達(dá)下偏振片時,被下偏振片吸收,無法到達(dá)反射板形成反射光,所以呈現(xiàn)黑色。這樣控制電路可以根據(jù)顯示的字符、圖形的需要控制液晶盒上、下電極之間的電壓,使得部分LCD顯示器中的部分點呈透明狀,而另一些點呈黑色,就可以在LCD顯示器上顯示各種字符或圖形。圖7-11LCD顯示器工作原理示意圖段式LCD顯示器是將液晶盒各段的其中一個電極連在一起,另一個電極作為獨立引腳,相應(yīng)的控制電路直接控制液晶盒上、下電極之間的電壓,使各段處于亮或滅的狀態(tài),從而組合出不同的字符。段式LCD液晶盒上、下電極之間的電壓必須采用一定頻率的交流信號,否則容易損壞LCD顯示器。段式LCD顯示器的驅(qū)動電路可以采用專用的段式LCD驅(qū)動芯片。當(dāng)段式LCD顯示位比較多時,其驅(qū)動電路也相應(yīng)比較復(fù)雜,面積也會增加。字符型LCD顯示器是一種通用的顯示器件,常見的字符型LCD的型號大多數(shù)以其每行能夠顯示的字符個數(shù)和顯示字符的行數(shù)來命名。如0802(2行,每行8個字符)、1601(1行,每行16個字符)、1602(2行,每行16個字符)、2004(4行,每行20個字符)等。所有字符型LCD顯示器的接口都相同。圖7-12是2行×16個字符(1602)的字符型LCD顯示器的外型圖和引腳排列。該顯示器由32個字符點陣塊組成,每個字符點陣塊由5×7或5×10個點陣組成,可以顯示ASCII碼表中的所有可視的字符。其內(nèi)部ROM中存儲有ASCII碼字符表,器件內(nèi)部有若干個用戶自編程字符存儲區(qū),允許用戶編寫ASCII碼字符表之外的特殊字符或圖形。器件內(nèi)部還具有數(shù)據(jù)RAM存儲器,用于保存顯示數(shù)據(jù)。大多數(shù)字符型LCD顯示器都以模塊(Module)形狀使用,LCD顯示器模塊(LCM)中有LCD驅(qū)動電路(點陣的行和列掃描電路)和接口控制器電路,有些字符型LCD顯示器模塊還帶有背光板(BackLightingBoard)組件。LCM的接口控制器是連接主控制器的通道,目前常用的LCM接口控制器有Hitachi公司的HD44780和Samsung公司的SED1278等,它們的時序、接口電路互相兼容。圖7-12字符型LCD顯示器外型和引腳排列、名稱標(biāo)準(zhǔn)的字符型LCD顯示器模塊的接口引腳名稱和引腳功能如表7-3所示。字符型LCD顯示器模塊是一種智能器件,它的內(nèi)部有兩種寄存器:指令寄存器和數(shù)據(jù)寄存器。單片機(jī)等主控制系統(tǒng)對LCM的指令寄存器寫操作,可以將“清屏”等控制指令發(fā)送給LCM;對指令寄存器讀操作,得到的數(shù)據(jù)的最高位是LCM的狀態(tài)(空閑狀態(tài)或忙狀態(tài))標(biāo)志位,低7位是地址計數(shù)器信息。對LCM的數(shù)據(jù)存儲器寫操作,可以修改當(dāng)前地址中的顯示字符;讀操作可以得到當(dāng)前顯示地址中的顯示數(shù)據(jù)。字符型LCD顯示器模塊的詳細(xì)指令如表7-4所示。

LCM的顯示數(shù)據(jù)存儲器DDRAM與顯示屏上的字符顯示位置是一一對應(yīng)的,表7-5給出了LCM2004(4行,每行20個字符)的DDRAM地址與字符顯示位置的對應(yīng)關(guān)系。當(dāng)單片機(jī)等主控制器系統(tǒng)需要把字符顯示在屏幕的某一位置時,首先將對應(yīng)位置的DDRAM的地址寫到地址計數(shù)器(指令寄存器)中,然后再將該字符的ASCII碼寫入DDRAM中,這樣就可以完成一個字符的顯示。字符型LCD顯示器模塊的接口讀/寫操作時序如圖7-13和圖7-14所示,其時序參數(shù)見表7-6。值得注意的是,LCM的讀/寫時序不兼容IntelBus時序,而MCS-51系列單片機(jī)的“三總線”時序兼容IntelBus時序,所以后面介紹的MCS-51單片機(jī)與LCM接口電路和接口控制程序都是按照圖7-13和圖7-14所示的讀/寫操作時序進(jìn)行設(shè)計的。圖7-13LCM接口讀操作時序圖7-14LCM接口寫操作時序

MCS-51單片機(jī)與LCM接口的典型電路如圖7-15所示。圖中利用P2.7(AB15)和WR、RD邏輯組合后作為LCM1602的使能控制;P1.0和P1.1分別作為LCM的RS和R/W的控制信號。當(dāng)MCS-51單片機(jī)對外部地址7FFFH單元進(jìn)行讀或?qū)懖僮鲿r,LCM1602的工作使能端有效,驅(qū)動程序通過設(shè)置P1.0和P1.1的電平狀態(tài)以選擇LCM1602的命令或數(shù)據(jù)寄存器及LCM1602的讀或?qū)懖僮?。該電路的地址和I/O端口狀態(tài)與LCM寄存器的對應(yīng)關(guān)系見表7-7。圖7-15MCS-51單片機(jī)與LCM1602的接口電路按照圖7-15所示的接口電路,相應(yīng)的接口控制程序如下:#include<io51.h>#include<string.h>#define

LCDRS

P1.0

//LCD的RS控制線#define

LCDRW

P1.1

//LCD的R/W控制線#define

ReadLCMCmdReg LCDRS=0;\

LCDRW=1

//設(shè)置LCM進(jìn)入“讀命令”操作#define

WriteLCMCmdReg

LCDRS=0;\

LCDRW=0

//設(shè)置LCM進(jìn)入“寫命令”操作#define

ReadLCMDataReg

LCDRS=1;\

LCDRW=1

//設(shè)置LCM進(jìn)入“讀數(shù)據(jù)”操作#define

WriteLCMDataReg

LCDRS=1;\

LCDRW=0

//設(shè)置LCM進(jìn)入“寫數(shù)據(jù)”操作#define

LCMPORTAdr*(unsignedchar*)(0x017FFF)

//LCM的地址codeTestScreen[][]={{“LCMInterface”},{“ZJUT2001/10”}};

//測試字符串unsignedcharReadBusyandACFromLCM(void)

//讀忙標(biāo)志和地址計數(shù)器{

unsignedcharresult;

ReadLCMCmdReg;

//置LCD-RS=0,LCD-RW=1

result=LCMPORTAdr;

//讀LCM的忙標(biāo)志和地址計數(shù)器

return(result);

//返回忙標(biāo)志(MSB=Bsy)和地址計數(shù)器}voidWriteDataToLCM(unsignedchar_data)

//寫數(shù)據(jù)操作{

WriteLCMDataReg;

//置LCD-RS=1,LCD-RW=0

LCMPORTAdr=_data; //寫數(shù)據(jù)到LCM的數(shù)據(jù)寄存器

do{

_data=ReadBusyandACFromLCM();

}while((_data&0x80)==0x80); //等待LCM操作完畢}voidInit_LCM1602(void)

//初始化LCM操作{

Delay(100);

WriteCommandToLCM(0x38);

//連續(xù)執(zhí)行3次,等待LCM上電自復(fù)位結(jié)束

Delay(80);

WriteCommandToLCM(0x38);

Delay(80);

WriteCommandToLCM(0x38);

//設(shè)置接口DB寬度(8位)和LCM顯示行數(shù)(2行)

Delay(80);

WriteCommandToLCM(0x01); //執(zhí)行清屏操作

Delay(50);

WriteCommandToLCM(0x06); //設(shè)置光標(biāo)為加1模式

Delay(50);

WriteCommandToLCM(0x0C); //設(shè)置光標(biāo)為移位模式

Delay(50);}voidGotoXYofLCMScreen(unsignedcharx,unsignedchary){

x&=0x01;

//顯示行數(shù)僅可以為0或1,即第1或2行

y&=0x0F;

//顯示的列位置僅可以為0~F

y|=(x==0)?0x40:0xC0;

//判斷是第1或2行

WriteCommandToLCM(y);

//寫到LCM的地址計數(shù)器

do{

y=ReadBusyandACFromLCM();

while((y&0x80)==0x80);

//等待LCM操作完畢}voidPutCharonLCMScreen(unsignedcharx,unsignedchary,

unsignedchar_char);

//顯示一個字符在屏幕中指定的位置(x,y){

GotoXYofLCMScreen(x,y); //當(dāng)前顯示器地址轉(zhuǎn)向(x,y)

WriteDataToLCM(_char); //將字符(_char)寫到當(dāng)前顯示地址}voidPutStrToLCMScreen(unsignedcharx,unsignedchary,

unsignedchar*str,unsignedcharlen){ //從屏幕中指定的位置(x,y)開始顯示字符串str

unsignedchari;

for(i=0;i<len;i++)

{

PutCharonLCMScreen(x,y++,str[i]);

//將一個字符寫到當(dāng)前顯示地址

if(y>0x0F)

//顯示自動換行調(diào)整操作

{

y=0;

//下一行的第1列

x++;

//下一行

}

}}voidmain(void) //主程序調(diào)用上面的子程序,顯示兩個字符串{

//8051初始化程序

Init_LCM1602();

//初始化LCM(2行,8位并行接口)

PutStrToLCMScreen(0,0,TestScreen[0][0],16);

//從(0,0)開始顯示顯示"_LCM_Interface__"

PutStrToLCMScreen(0,0,TestScreen[1][0],16);

//從(1,0)開始顯示顯示"__ZJUT_2002/10__"

...

//繼續(xù)執(zhí)行其他任務(wù)}7.2.3圖形點陣LCD顯示器的接口目前常用的圖形點陣LCD顯示器一般都采用模塊結(jié)構(gòu)(稱為圖形LCM)。MCS-51單片機(jī)與圖形點陣LCD顯示器接口電路取決于顯示模塊的接口控制器。目前常用的圖形LCM的接口控制器有:Toshiba公司的T6963C、Hitachi公司的HD61830、Samsung公司的“KS0107+KS0108”(分別為行和列驅(qū)動)等。接口控制器不同,它們與單片機(jī)的接口電路、時序和接口控制軟件也不完全相同。圖7-16是G12864圖形LCM的內(nèi)部結(jié)構(gòu)框圖,它采用Samsung公司的圖形LCD驅(qū)動控制器,其屏幕由64(行)×128(列)點陣組成,可以顯示16點陣的4行×8列(32個)漢字或128×64全屏幕點陣圖形。該模塊的控制板上帶有圖形LCM必需的對比度調(diào)節(jié)負(fù)電壓產(chǎn)生電路,設(shè)計接口電路時可以直接利用該LCM輸出的負(fù)電壓(VEE)。而且LCM的控制板中還具有背光板高壓驅(qū)動電路,用戶接口電路對背光板的控制采用兼容TTL邏輯電平。它采用單DC+5V供電,功耗極低,當(dāng)背光板關(guān)閉時,消耗電流3mA;當(dāng)背光板亮?xí)r,消耗電流小于50mA。它與MCS-51單片機(jī)等主控制系統(tǒng)采用8位并行接口及20引腳連接器,各引腳名稱和功能如表7-8所示。圖7-16G12864圖形LCM的內(nèi)部結(jié)構(gòu)

G12864圖形LCD顯示器使用7種指令與單片機(jī)等主控制器之間通信,7種指令的詳細(xì)格式和參數(shù)見表7-9。在表7-9中所謂的頁地址就是DDRAM的行地址,8行為一頁,LCMG12864共64行,即8頁,A2~A0用于選擇第0~7頁。讀/寫數(shù)據(jù)對頁地址沒有影響,頁地址為當(dāng)前指令指定的位置或復(fù)位后位于第0頁地址。頁地址與DDRAM的對應(yīng)關(guān)系如表7-10所示。

MCS-51單片機(jī)在執(zhí)行指令“設(shè)y地址”時,將新的6位y地址寫到y(tǒng)地址計數(shù)器中。當(dāng)單片機(jī)對DDRAM中的數(shù)據(jù)進(jìn)行讀或?qū)懖僮?讀/寫數(shù)據(jù))時,y地址計數(shù)器會加1,指向下一個地址。圖7-17是G12864顯示模塊與主控制系統(tǒng)的接口讀/寫操作時序,其時間參數(shù)見表7-11。圖7-17G12864讀/寫操作時序(a)讀操作時序;(b)寫操作時序根據(jù)圖7-17所示的操作時序,設(shè)計如圖7-18所示的G12864與MCS-51單片機(jī)的接口電路。由于G12864接口時序的特殊性,采用MCS-51單片機(jī)的擴(kuò)展I/O端口作為G12864的控制信號,擴(kuò)展的I/O端口Bit.0和Bits.1分別作為兩片列驅(qū)動器(KS0108A-1和KS0108A-2)的片選控制,這兩個信號任何時刻僅允許一個輸出高有效電平。選通其中的一片列驅(qū)動器,當(dāng)Bit.0=1且Bit.1=0時,第1片列驅(qū)動器被選中;Bit.0=0且Bit.1=1時,第2片列驅(qū)動器被選中。Bit.2作為LCM的指令和數(shù)據(jù)寄存器選擇控制信號,Bit.3作為LCM讀/寫選擇控制信號。Bit.6控制LCM的復(fù)位和運(yùn)行狀態(tài),Bit.6=0,復(fù)位LCM;正常運(yùn)行狀態(tài)時Bit.6=1。Bit.7作為G12864的背光板打開或關(guān)閉控制信號,Bit.7=1,背光板被打開;Bit.7=0,背光板被關(guān)閉。G12864的使能控制信號受P2.7(AB15)控制,當(dāng)AB15=0時,8051執(zhí)行讀操作即讀LCM的數(shù)據(jù)寄存器或指令寄存器;當(dāng)AB15=1時,8051執(zhí)行寫操作即寫LCM的指令寄存器或數(shù)據(jù)寄存器。擴(kuò)展的8位鎖存器的寫鎖存信號受P2.6(AB14)控制,當(dāng)AB14=0時,8051可以將控制G12864狀態(tài)字鎖存到擴(kuò)展的I/O輸出端口處。圖7-18MCS-51單片機(jī)與LCM12864的接口電路圖形點陣LCD顯示器可以直接顯示漢字和圖形、曲線,其原理是控制LCD點陣中的點的亮或暗,亮和暗的點陣按一定規(guī)律可以組成漢字,組成一幅、若干幅圖形和曲線。而所有的LCM都帶有顯示緩存,單片機(jī)等主控制器只需要將點陣的亮和暗控制信息寫到LCM的顯示緩存中,LCM的行、列驅(qū)動器會自動掃描LCD點陣,保持用戶期望的顯示效果。所有的LCM顯示緩存都采用字節(jié)方式讀/寫,對用戶來講,LCM屏幕上的點陣是按字節(jié)方式8個點一組來控制的。一個16點陣的漢字在LCM的屏幕上是采用16×16個點來表達(dá)的,即一個16點陣的漢字需要32個字節(jié)的編碼數(shù)據(jù),這些編碼數(shù)據(jù)包含16×16點陣中亮和暗的控制信息。

G12864是一種全屏幕點陣圖形顯示器,可以在G12864的屏幕上僅顯示一幅128×64點陣的圖形或曲線。當(dāng)用它來顯示漢字或字符時,可以按照漢字或字符點陣的大小任意分割成多個小點陣塊。如果用來顯示16×16點陣的漢字,可以分割成32個16×16點陣塊,能夠顯示32個漢字;如果用來顯示32×32點陣漢字,能夠顯示8個32×32點陣漢字。下面就是在G12864顯示器上顯示16×16點陣漢字的程序:#include<io51.h>#include<string.h>#define

LCMCWAdr*(unsignedchar*)(0x01BFFF)

//LCM控制字鎖存器端口地址#defineLCMPORTAdr*(unsignedchar*)(0x017FFF) //LCM讀/寫使能端口地址#define

_CS1

0x01

//指定各控制信號在鎖存器中的位置(硬件有關(guān))#define

_CS2 0x02#define

_DI

0x04#define

_RW

0x08#define

_RST

0x40#define

_ELON

0x80unsignedcharidataELState=0;

//是否允許背光板亮的狀態(tài)寄存器codeunsignedcharTestHZDotCode[][]={

//將“機(jī)電一體化”5個漢字的編碼保存在Code區(qū){

0x00,0x0C,0x07,0x7F,0x61,0x03,0x42,0x30,

0x0F,0x00,0x00,0x00,0x7F,0x40,0x60,0x00,

0x00,0x30,0x10,0xFE,0x16,0x90,0x10,0x00,

0xFC,0x04,0x04,0x04,0xFC,0x00,0x00,0x00},

//漢字“機(jī)”的編碼{

0x00,0x00,0x00,0x1F,0x04,0x04,0x04,0x7F,

0x44,0x44,0x44,0x44,0x47,0x60,0x20,0x00,

0x00,0x00,0x00,0xF0,0x90,0x90,0x90,0xFE,

0x90,0x90,0x90,0x90,0xF0,0x00,0x00,0x00},

//漢字“電”的編碼{

0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,

0x01,0x

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論