單片機原理與應用設計(C51編程+Proteus仿真)(第4版) 課件 第5章與顯示器、開關、鍵盤接口設計_第1頁
單片機原理與應用設計(C51編程+Proteus仿真)(第4版) 課件 第5章與顯示器、開關、鍵盤接口設計_第2頁
單片機原理與應用設計(C51編程+Proteus仿真)(第4版) 課件 第5章與顯示器、開關、鍵盤接口設計_第3頁
單片機原理與應用設計(C51編程+Proteus仿真)(第4版) 課件 第5章與顯示器、開關、鍵盤接口設計_第4頁
單片機原理與應用設計(C51編程+Proteus仿真)(第4版) 課件 第5章與顯示器、開關、鍵盤接口設計_第5頁
已閱讀5頁,還剩142頁未讀, 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第5章單片機的開關檢測、鍵盤輸入

與顯示的接口設計

1單片機系統顯示及開關檢測、鍵盤輸入是其基本功能。本章介紹單片機與顯示器件、開關及鍵盤的接口設計與軟件編程。5.1單片機控制發光二極管顯示發光二極管常用來指示系統工作狀態,制作節日彩燈、廣告牌匾等。大部分發光二極管工作電流1~5mA之間,其內阻為20~100Ω。電流越大,亮度也越高。為保證發光二極管正常工作,同時減少功耗,限流電阻選擇十分重要,若供電電壓為+5V,則限流電阻可選1~3kΩ。25.1.1單片機與發光二極管的連接第2章已介紹,P0口作通用I/O用,由于漏極開路,需外接上拉電阻。而P1~P3口內部有30kΩ左右上拉電阻。下面討論P1~P3口如何與LED發光二極管驅動連接問題。單片機并行端口P1~P3直接驅動發光二極管,電路見圖5-1。與P1、P2、P3口相比,P0口每位可驅動8個LSTTL輸入,而P1~P3口每一位驅動能力,只有P0口一半。圖5-1

發光二極管與單片機并行口的連接當P0口某位為高電平時,可提供400μA的拉電流;當P0口某位為低電平(0.45V)時,可提供3.2mA的灌電流,而P1~P3口內有30kΩ左右上拉電阻,如高電平輸出,則從P1、P2和P3口輸出的拉電流Id僅幾百μA,驅動能力較弱,亮度較差,見圖5-1(a)。如端口引腳為低電平,能使灌電流Id從單片機外部流入內部,則將大大增加流過的灌電流值,見圖5-1(b)。AT89S51任一端口要想獲得較大的驅動能力,要用低電平輸出。如一定要高電平驅動,可在單片機與發光二極管間加驅動電路,如74LS04、74LS244等。5.1.2I/O端口的編程控制

對I/O端口編程控制時,要對I/O端口特殊功能寄存器聲明,在C51的編譯器中,這項聲明包含在頭文件reg51.h中,編程時,可通過預處理命令#include<reg51.h>,把這個頭文件包含進去。下面通過案例介紹如何編程對發光二極管輸出控制。6

【例5-1】

制作流水燈,原理電路見圖5-2,8個發光二極管LED0~LED7經限流電阻分別接至P1口的P1.0~P1.7引腳上,陽極共同接高電平。編寫程序來控制發光二極管由上至下的反復循環流水點亮,每次點亮一個發光二極管。參考程序:#include<reg51.h>#include<intrins.h> //包含移位函數_crol_()的頭文件#defineucharunsignedchar #defineuintunsignedint voiddelay(uinti) //延時函數{ uchart; while(i--)

78圖5-2

單片機控制的流水燈 { for(t=0;t<120;t++); }}voidmain() //主程序{

P1=0xfe; //向P1口送出點亮數據

while(1) { delay(500); //500為延時參數,可根據實際需要調整

P1=_crol_(P1,1); //函數_crol_(P1,1)把P1中的數據循環左移1位

}}9程序說明:(1)while(1)兩種用法:“while(1);”:

while(1)后有分號,是使程序停留在這指令上;“while(1){……;}”:反復循環執行大括號內程序段,本例用法,即控制流水燈反復循環顯示。

(2)C51函數庫中的循環移位函數:循環移位函數包括:

循環左移函數“_crol_”

循環右移函數“_cror_”。本例用循環左移“_crol_(P1,1)”,函數。括號第1個參數為循環左移對象,即對P1中的內容循環左移;第2個參數為左移位數,即左移1位。編程中一定要把含有移位函數的頭文件intrins.h包含在內,例如第2行“#include<intrins.h>”。10在【例5-1】基礎上,編寫控制發光二極管反復循環點亮的流水燈?!纠?-2】電路見圖5-2,制作由上至下再由下至上反復循環點亮顯示的流水燈,3種方法實現。(1)數組的字節操作實現建立1個字符型數組,將控制8個LED顯示的8位數據作為數組元素,依次送P1口。參考程序:#include<reg51.h>#defineucharunsignedchar uchartab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,

0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; /*前8個數據為左移點亮數據,后8個為右移點亮數據*/voiddelay(){ uchari,j; for(i=0;i<255;i++) for(j=0;j<255;j++);}voidmain() //主函數{ uchari; while(1) { for(i=0;i<16;i++) {

P1=tab[i]; //向P1口送出點亮數據

delay(); //延時,即點亮一段時間

} }}12(2)移位運算符實現使用移位運算符“>>”、“<<”,把送P1口顯示控制數據進行移位,從而實現發光二極管依次點亮。參考程序:#include<reg51.h>#defineucharunsignedchar

voiddelay(){ uchari,j; for(i=0;i<255;i++) for(j=0;j<255;j++);}voidmain() //主函數{ uchari,temp; while(1)13{ temp=0x01; //左移初值賦給temp for(i=0;i<8;i++) {

P1=~temp; //temp中的數據取反后送P1口

delay(); //延時

temp=temp<<1; //temp中數據左移一位

} temp=0x80; //賦右移初值給temp for(i=0;i<8;i++) {

P1=~temp; //temp中的數據取反后送P1口

delay(); //延時

temp=temp>>1; //temp中數據右移一位

} }}14

程序說明:

注意使用移位運算符“>>”、“<<”與使用循環左移函數“_crol_”和循環右移函數“_cror_”區別。左移移位運算“<<”是將高位丟棄,低位補0;右移移位運算、“>>”是將低位丟棄,高位補0。而循環左移函數“_crol_”是將移出的高位再補到低位,即循環移位;同理循環右移函數“_cror_”是將移出的低位再補到高位。(3)用循環左、右移位函數實現使用C51提供的庫函數,即循環左移n位函數和循環右移n位函數,控制發光二極管點亮。參考程序:#include<reg51.h>#include<intrins.h> //包含循環左、右移位函數的頭文件#defineucharunsignedchar 15voiddelay(){ uchari,j; for(i=0;i<255;i++) for(j=0;j<255;j++);}voidmain() //主函數{ uchari,temp; while(1) {

temp=0xfe; //初值為11111110 for(i=0;i<7;i++)

{ P1=temp; //temp中的點亮數據送P1口,控制點亮顯示

delay(); //延時

temp=_crol_(temp,1); //

temp數據循環左移1位

} for(i=0;i<7;i++) { P1=temp; //temp中的數據送P1口輸出

delay(); //延時

temp=_cror_(temp,1); //temp中數據循環右移1位

}}}175.2開關狀態檢測讀入I/O端口電平,即可檢測開關處于閉合狀態還是打開狀態。5.2.1開關檢測實例1用I/O端口來進行開關狀態檢測,開關一端接到I/O端口引腳上,并通過上拉電阻接+5V上,開關另一端接地,當開關打開時,I/O引腳為高電平,當開關閉合時,I/O引腳為低電平。18【例5-3】

如圖5-3,單片機的P1.4~P1.7接4個開關S0~S3,P1.0~P1.3接4個發光二極管LED0~LED3。編程將P1.4~P1.7上的4個開關狀態反映在P1.0~P1.3引腳控制的4個發光二極管上,開關閉合,對應發光二極管點亮。例如P1.4引腳上開關S0狀態,由P1.0腳上LED0顯示,P1.6引腳上開關S2狀態,由P1.2腳的LED2顯示。1920圖5-3

開關、LED發光二極管與P1口的連接參考程序如下:#include<reg51.h>#defineucharunsignedcharvoiddelay() //延時函數{ uchari,j; for(i=0;i<255;i++) for(j=0;j<255;j++);}voidmain() //主函數{while(1){ unsignedchartemp; //定義臨時變量temp P1=0xff;//P1口低4位置1,作為輸入;高4位置1,發光二極管熄滅

temp=P1&0xf0; //讀P1口并屏蔽低4位,送入temp中

21

temp=temp>>4;//temp內容右移4位,P1口高4位移至低4位

P1=temp; //temp中的數據送P1口輸出

delay( );}5.2.2開關檢測實例2【例5-4】

如圖5-4,P1.0和P1.1引腳接有兩只開關S0和S1,兩引腳上的高低電平共4種組合,4種組合分別點亮P2.0~P2.3引腳控制的4只LED,即S0、S1均閉合,LED0亮,其余滅;S1閉合、S0打開,LED1亮,其余滅;S0閉合、S1打開,LED2亮,其余滅;S0、S1均打開,LED3亮,其余滅。編程實現此功能。參考程序:23圖5-4

開關檢測指示器2接口電路與仿真#include<reg51.h> //包含頭文件reg51.hvoidmain() //主函數main(){ charstate; do {

P1=0xff; //P1口為輸入

state=P1; //讀入P1口的狀態,送入state

state=state&0x03; //屏蔽P1口的高6位

switch(state) //判P1口低2位開關狀態

{ case0:P2=0x01;break;//P1.1、P1.0=00,點亮P2.0腳LED

case1:P2=0x02;break;//P1.1、P1.0=01,點亮P2.1腳LED

case2:P2=0x04;break;//P1.1、P1.0=10,點亮P2.2腳LED

case3:P2=0x08;break;//P1.1、P1.0=11,點亮P2.3腳LED

} }while(1);}24程序段中用到循環結構控制語句do-while以及switch-case語句。5.3單片機控制LED數碼管的顯示5.3.1LED數碼管顯示原理LED數碼管:“8”字型,7段(不包括小數點)或8段(包括小數點),每段對應一個發光二極管,共陽極和共陰極兩種,見圖5-5。共陽極數碼管的陽極連接在一起,接+5V;共陰極數碼管陰極連在一起接地。對于共陰極數碼管,當某發光二極管陽極為高電平時,發光二極管點亮,相應段被顯示。同樣,共陽極數碼管陽極連在一起,公共陽極接+5V,當某個發光二極管陰極接低電平時,該發光二極管被點亮,相應段被顯示。26圖5-58段LED數碼管結構及外形為使LED數碼管顯示不同字符,要把某些段點亮,就要為數碼管各段提供一字節的二進制碼,即段碼(也稱字型碼)。習慣上以“a”段對應字型碼字節的最低位。各字符段碼見表5-1。2728如要在數碼管顯示某字符,只需將該字符字型碼加到各段上即可。例如某存儲單元中的數為“02H”,想在共陽極數碼管上顯示“2”,需要把“2”的字型碼“A4H”加到數碼管各段。將欲顯示字符的字型碼作成一個表(數組),根據顯示字符從表中查找到相應字型碼,然后把該字型碼輸出數碼管各個段上,同時數碼管的公共端接+5V,此時在數碼管上顯示字符“2”。下面介紹單片機如何控制LED數碼管顯示字符?!纠?-5】利用單片機控制一個8段LED數碼管先循環顯示單個偶數:0、2、4、6、8,再顯示單個奇數:1、3、5、7、9,如此反復循環顯示。本例原理電路及仿真結果,見圖5-6。參考程序如下:圖5-6

控制數碼管循環顯示單個數字的電路及仿真#include"reg51.h"#include"intrins.h"#defineucharunsignedchar#defineuintunsignedint#defineoutP0ucharcodeseg[]={0xc0,0xa4,0x99,0x82,0x80,0xf9,0xb0,0x92,0xf8,0x90,0x01};//共陽極段碼表voiddelayms(uint); voidmain(void){ uchari; while(1) {

out=seg[i]; delayms(900); i++;

31if(seg[i]==0x01)i=0; //如段碼為0x01,表明一個循環顯示已結束

}}voiddelayms(uintj) //延時函數 {uchari;for(;j>0;j--) { i=250; while(--i); i=249; while(--i); }}

說明:語句“if(seg[i]==0x01)i=0;”含義:如果欲送出的數組元素為0x01(數字“9”段碼0x90的下一個元素,即結束碼),表明一個循環顯32示已結束,則i=0,則重新開始循環顯示,從段碼數組表的第一個元素seg[0],即段碼0xc0(數字0)重新開始顯示。5.3.2LED數碼管的靜態顯示與動態顯示兩種顯示方式:靜態顯示和動態顯示。1.靜態顯示方式無論多少位LED數碼管,都同時處于顯示狀態。多位LED數碼管工作于靜態顯示方式時,各位共陰極(或共陽極)連接在一起并接地(或接+5V);每位數碼管段碼線(a~dp)分別與一個8位I/O口鎖存器輸出相連。如果送往各個LED數碼管所顯示字符的段碼一經確定,則相應I/O口鎖存器鎖存的段碼輸出將維持不變,直到送入下一個顯示字符段碼。靜態顯示方式顯示無閃爍,亮度較高,軟件控制較易。

圖5-7為4位LED數碼管靜態顯示電路,各數碼管可獨立顯示,只要向控制各位I/O口鎖存器送相應顯示段碼,該位就能保持相應的顯示字符。這樣在同一時間,每一位顯示的字符可各不相同。靜態顯示方式占用I/O口端口線較多。圖5-7電路,要占用4個8位I/O口(或鎖存器)。如數碼管數目增多,則需增加I/O口數目。34圖5-74位LED靜態顯示的示意圖【例5-6】單片機控制2只數碼管,靜態顯示2個數字“27”。原理電路見圖5-8。單片機用P0口與P1口,分別控制加到兩個數碼管DS0與DS1的段碼,而共陽極數碼管DS0與DS1的公共端(公共陽極端)直接接至+5V,因此數碼管DS0與DS1始終處于導通狀態。利用P0口與P1口帶有的鎖存功能,只需向單片機P0口與P1口分別寫入相應的顯示字符“2”和“7”的段碼即可。由于一個數碼管就占用一個I/O端口。如果數碼管數目增多,則需增加I/O口,但軟件編程要簡單的多。36圖5-82位數碼管靜態顯示的原理電路與仿真參考程序如下:#include<reg51.h> //包含8051單片機寄存器定義的頭文件voidmain(void){

P0=0xa4; //將數字"2"的段碼送P0口

P1=0xf8; //將數字"7"的段碼送P1口

while(1) //無限循環

;}

2.動態顯示方式顯示位數較多時,靜態顯示所占的I/O口多,這時常采用動態顯示。為節省I/O口,通常將所有顯示器段碼線相應段并聯在一起,由一個8位I/O口控制,各顯示位公共端分別由另一單獨I/O口線控制。3839圖5-94位LED數碼管動態顯示示意圖圖5-9為4位8段LED動態顯示器電路示意圖。其中單片機發出的段碼占用1個8位I/O(1)端口,而位選控制使用I/O(2)端口中4位口線。動態顯示就是單片機向段碼線輸出欲顯示字符的段碼。每一時刻,只有1位位選線有效,即選中某一位顯示,其他各位位選線都無效。每隔一定時間逐位輪流點亮各數碼管(掃描方式),由于數碼管余輝和人眼的“視覺暫留”作用,只要控制好每位數碼管顯示時間和間隔,則可造成“多位同時亮”的假象,達到同時顯示效果。各位數碼管輪流點亮的時間間隔(掃描間隔)應根據實際情況定。發光二極管從導通到發光有一定的延時,如果點亮時間太短,發光太弱,人40眼無法看清;時間太長,產生閃爍現象,且此時間越長,占用單片機時間也越多。另外,顯示位數增多,也將占用單片機大量時間,因此動態顯示實質是以執行程序時間來換取I/O端口減少。下面是動態顯示實例?!纠?-7】8只數碼管,分別滾動顯示單個數字1~8。程序運行后,單片機控制左邊第1個數碼管顯示1,其他不顯示,延時之后,控制左邊第2個數碼管顯示1,其他不顯示,直至第8個數碼管顯示8,其他不顯示,反復循環上述過程。動態顯示電路見圖5-10,P0口輸出段碼,P2口輸出掃描的位控碼,通過由8個NPN晶體管的位驅動電路對8個數碼管位控掃描。如對本例實際硬件顯示電路進行快速掃描,由于數碼管余輝和人眼“視覺暫留”作用,只要控制好每位數碼管顯示的時間和間隔,則可造成“多位同時亮”假象,達到同時顯示效果。圖5-108只數碼管逐個顯示單個數字1~8參考程序如下:#include<reg51.h>#include<intrins.h>#defineucharunsignedchar#defineuintunsignedintucharcodedis_code[]={0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0xc0};

//共陽數碼管段碼表voiddelay(uintt) //延時函數{ uchari; while(t--)for(i=0;i<200;i++);}voidmain(){ uchari,j=0x80;43while(1){ for(i=0;i<8;i++) { j=_crol_(j,1); //_crol_(j,1)為將對象j循環左移1位

P0=dis_code[i]; //P0口輸出段碼

P2=j; //P2口輸出位控碼

delay(180); //延時,控制每位顯示的時間

}}}5.4單片機控制LED點陣顯示器顯示

目前,LED點陣顯示器應用非常廣泛,在許多公共場合,如商場、銀44行、車站、機場、醫院隨處可見。不僅能顯示文字、圖形,還能播放動畫、圖像、視頻等信號。LED點陣顯示屏分為圖文顯示器和視頻顯示器,有單色顯示,還有彩色顯示。下面僅介紹單片機如何來控制單色LED點陣顯示屏的顯示。5.4.1LED點陣顯示器結構與顯示原理由若干個發光二極管按矩陣方式排列而成。陣列點數可分為5×7、5×8、6×8、8×8點陣;按發光顏色可分為單色、雙色、三色;按極性排列可分為共陰極和共陽極。1.LED點陣結構以8×8LED點陣顯示器為例,外形見圖5-11,內部結構見圖5-12,由64個發光二極管組成,且每個發光二極管是處于行線(R0~R7)和列線(C0~C7)之間交叉點上。2.LED點陣顯示原理顯示的字符由一個個點亮的LED所構成。由圖5-12點亮點陣中一個發光二極管條件:對應行為高電平,對應列為低電平。如在很短時間內依次點亮很多個發光二極管,LED點陣就可顯示一個穩定字符、數字或其他圖形。控制LED點陣顯示器顯示,實質就是圖5-118×8LED點陣顯示器外形圖5-128×8LED點陣顯示器(共陰極)的結構控制加到行線和列線上編碼,控制點亮某些發光二極管(點),從而顯示出由不同發光點組成的各種字符。16×16LED點陣顯示器的結構與8×8LED點陣顯示模塊內部結構及顯示原理是類似的,只不過行和列均為16。16×16是由4個8×8LED點陣組成,且每個發光二極管也是放置在行線和列線的交叉點上,當對應某一列置0電平,某一行置1電平時,該發光二極管點亮。下面以顯示字符“子”為例,見圖5-13。圖5-1316×16LED點陣顯示器顯示字符“子”顯示過程如下:先給LED點陣的第1行送高電平(行線高電平有效),同時給所有列線送高電平(列線低電平有效),從而第1行發光二極管全滅;延時一段時間后,再給第2行送高電平,同時給所有列線送“1100000000001111”,列線為0的發光二極管點亮,從而點亮10個發光二極管,顯示出漢字“子”的第一橫;延時一段時間后,再給第3行送高電平,同時加到列線的編碼為“1111111111011111”,點亮1個發光二極管;……;延時一段時間后,再給第16行送高電平,同時給列線送“1111110111111111”,顯示出漢字“子”的最下面的一行,點亮1個發光二極管。然后再重新循環上述操作,利用人眼視覺暫留效應,一個穩定字符“子”顯示

出來,見圖5-13。5.4.2控制16×16LED點陣顯示屏的案例

【例5-8】如圖5-14,利用單片機及74HC154(4-16譯碼器)、74LS07、16×16LED點陣顯示屏來實現字符顯示,編寫程序,循環顯示字符“電子技術”。圖中16×16LED點陣顯示屏16行行線R0~R15電平,由P1口低4位經4-16譯碼器74HC154的16條譯碼輸出線L0~L15經驅動后的輸出來控制。16列列線C0~C15的電平由P0口和P2口控制。剩下問題是如何確定顯示字符的點陣編碼,以及控制好每一屏逐行顯示的掃描速度(刷新頻率)。圖5-14

控制16×16LED點陣顯示器(共陰極)顯示字符參考程序如下:#include<reg51.h>#defineucharunsignedchar#defineuintunsignedint#defineout0P0#defineout2P2#defineout1P1voiddelay(uintj) //延時函數{ uchari=250; for(;j>0;j--) { while(--i); i=100; }}ucharcodestring[]={//漢字“電”16×16點陣列碼0x7F,0xFF,0x7F,0xFF,0x7F,0xFF,0x03,0xE0,0x7B,0xEF,0x7B,0xEF,0x03,0xE0,0x7B,0xEF,0x7B,0xEF,0x7B,0xEF,0x03,0xE0,0x7B,0xEF,0x7F,0xBF,0x7F,0xBF,0xFF,0x00,0xFF,0xFF

//漢字“子”16×16點陣列碼0xFF,0xFF,0x03,0xF0,0xFF,0xFB,0xFF,0xFD,0xFF,0xFE,0x7F,0xFF,0x7F,0xFF,0x7F,0xDF,0x00,0x80,0x7F,0xFF,0x7F,0xFF,0x7F,0xFF,0x7F,0xFF,0x7F,0xFF,0x5F,0xFF,0xBF,0xFF//漢字“技”16×16點陣列碼0xF7,0xFB,0xF7,0xFB,0xF7,0xFB,0x40,0x80,0xF7,0xFB,0xD7,0xFB,0x67,0xC0,0x73,0xEF,0xF4,0xEE,0xF7,0xF6,0xF7,0xF9,0xF7,0xF9,0xF7,0xF6,0x77,0x8F,0x95,0xDF,0xFB,0xFF//漢字“術”的16×16點陣的列碼0x7F,0xFF,0x7F,0xFB,0x7F,0xF7,0x7F,0xFF,0x00,0x80,0x7F,0xFF,0x3F,0xFE,0x5F,0xFD,0x5F,0xFB,0x6F,0xF7,0x77,0xE7,0x7B,0x8F,0x7C,0xDF,0x7F,0xFF,0x7F,0xFF,0xFF,0xFF,};voidmain(){ uchari,j,n; while(1) { for(j=0;j<4;j++) //共顯示4個漢字

{for(n=0;n<40;n++) //每個漢字整屏掃描40次{ for(i=0;i<16;i++) //逐行掃描16行 {

out1=i%16; //輸出行碼,

out0=string[i*2+j*32]; //輸出列碼到C0~C7,逐行掃描

out2=string[i*2+1+j*32]; //輸出列碼到C8~C15,逐行掃描

delay(4); //顯示并延時一段時間

out0=0xff; //列線C0~C7為高電平,熄滅發光二極管

out2=0xff; /列線C8~C15為高電平,熄滅發光二極管

}

}}}}掃描顯示時,單片機通過P1口低4位經4-16譯碼器74HC154的16條譯碼輸出線L0~L15經驅動后的輸出來控制,逐行為高電平,來進行掃描。由P0口與P2口控制列碼的輸出,從而顯示出某行應點亮的發光二極管。以顯示漢字“子”為例,說明顯示過程。由上面程序可看出,漢字“子”的前3行發光二級管的列碼為“0xFF,0xFF,0x03,0xF0,0xFF,0xFB,……”第一行列碼為:“0xff,0xff”,由P0口與P2口輸出,無點亮的發光二極管。第二行列碼為:“0x03,0xf0”,通過P0口與P2口輸出后,由圖5-13看出,0x03加到列線C7~C0的二進制編碼為“00000011”,這里要注意加到8個發光二極管上的對應位置。按照圖5-12和圖5-14連線關系,加到從左到右發光二極管應為C0~C7的二進制編碼為“11000000”,即最左邊的2個發光二極管不亮,其余的6個發光二極管點亮。同理,P2口輸出的0xF0加到列線C15~C8的二進制編碼為“11110000”,即加到C8~C15的二進制編碼為“00001111”,所以第二行的最右邊的4個發光二極管不亮,如圖5-13所示。對應通過P0口與P2口輸出加到第3行16個發光二極管的列碼為“0xFF,0xFB,”,對應于從左到右的C0~C15的二進制編碼為“1111111111011111”,從而第3行左邊數第11個發光二極管被點亮,其余均熄滅,如圖5-13所示。其余各行點亮的發光二極管,也是由16×16點陣的列碼來決定。5.5單片機控制液晶顯示模塊1602LCD的顯示液晶顯示器(LiquidCrystalDisplay,LCD)具有省電、體積小、抗干擾能力強等優點,LCD顯示器分為字段型、字符型和點陣圖形型。(1)字段型。以長條狀組成字符顯示,主要用于數字顯示,也可用于顯示西文字母或某些字符,廣泛用于電子表、計算器、數字儀表中。(2)字符型。專門用于顯示字母、數字、符號等。一個字符由5×7或5×10的點陣組成,在單片機系統中已廣泛使用。(3)點陣圖形型。廣泛用于圖形顯示,如筆記本電腦、彩色電視和游戲機等。它是在平板上排列的多行列的矩陣式的晶格點,點大小與多少決定了顯示的清晰度。5.5.1LCD1602液晶顯示模塊簡介單片機系統中常用的字符型液晶顯示模塊。由于LCD顯示面板較為脆弱,廠商已將LCD控制器、驅動器、RAM、ROM和液晶顯示器用PCB連接到一起,稱為液晶顯示模塊(LCdModule,LCM),購買現成的即可。單片機只需向LCD顯示模塊寫入相應命令和數據就可顯示需要的內容。1.字符型液晶顯示模塊LCD1602特性與引腳字符型LCD模塊常用的有16字×2行、16字×4行、20字×2行、20字×4行等模塊,型號常用×××1602、×××1604、×××2002、×××2004來表示,其中×××為商標名稱,16代表液晶顯示器每行可顯示16個字符,02表示顯示2行。LCD1602內有字符庫ROM(CGROM),能顯示出192個字符(5×7點陣),如圖5-15所示。圖5-15ROM字符庫的內容由字符庫可看出顯示器顯示的數字和字母部分代碼,恰是ASCII碼表中編碼。單片機控制LCD1602顯示字符,只需將待顯示字符的ASCII碼寫入顯示數據存儲器(DDRAM),內部控制電路就可將字符在顯示器上顯示出來。例如,顯示字符“A”,單片機只需將字符“A”的ASCII碼41H寫入DDRAM,控制電路就會將對應的字符庫ROM(CGROM)中的字符“A”的點陣數據找出來顯示在LCD上。模塊內有80字節數據顯示RAM

(DDRAM),除顯示192個字符(5×7點陣)的字符庫ROM(CGROM)外,還有64字節的自定義字符RAM(CGRAM),用戶可自行定義8個5×7點陣字符。

(a)LCD1602的外形(b)LCD1602的引腳圖5-16LCD1602外形及引腳LCD1602工作電壓4.5~5.5V,典型5V,工作電流2mA。標準的14引腳(無背光)或16個引腳(有背光)的外形及引腳分布如圖5-16所示。引腳包括8條數據線、3條控制線和3條電源線,見表5-2。通過單片機向模塊寫入命令和數據,就可對顯示方式和顯示內容做出選擇。2.字符的顯示及命令字顯示字符首先要解決待顯示字符的ASCII碼產生。用戶只需在C51程序中寫入欲顯示的字符常量或字符串常量,C51程序在編譯后會自動生成其標準的ASCII碼,然后將生成的ASCII碼送入顯示用數據存儲器DDRAM,內部控制電路就會自動將該ASCII碼對應的字符在LCD1602顯示出來。讓液晶顯示器顯示字符,首先對其進行初始化設置:對有、無光標、光標移動方向、光標是否閃爍及字符移動方向等進行設置,才能獲得所需顯示效果。對LCD1602的初始化、讀、寫、光標設置、顯示數據的指針設置等,都是單片機向LCD1602寫入命令字來實現。命令字見表5-3。

表5-3中11個命令功能說明如下:命令1:清屏,光標返回地址00H位置(顯示屏的左上方)。命令2:光標返回到地址00H位置(顯示屏的左上方)。命令3:設置顯示模式。

I/D—地址指針加1或減1選擇位。

I/D=1,讀或寫一個字符后地址指針加1;

I/D=0,讀或寫一個字符后地址指針減1。S—屏幕上所有字符移動方向是否有效的控制位。

S=1,當寫入一字符時,整屏顯示左移(I/D=1)或右移(I/D=0);S=0,整屏顯示不移動。命令4:顯示開/關及光標設置。

D—屏幕整體顯示控制位,D=0關顯示,D=1開顯示。

C—光標有無控制位,C=0無光標,C=1有光標。

B—光標閃爍控制位,B=0不閃爍,B=1閃爍。命令5:光標或字符移位。

S/C—光標或字符移位選擇控制位。0:移動光標,1:移動顯示的字符。

R/L—移位方向選擇控制位。0:左移,1:右移,命令6:功能設置命令。DL—傳輸數據的有效長度選擇控制位。1:8位數據線接口;0:4位數據線接口。N—顯示器行數選擇控制位。0:單行顯示,1:兩行顯示。F—字符顯示的點陣控制位。0:顯示5×7點陣字符,1:顯示5×10點陣字符。命令7:CGRAM地址設置。命令8:DDRAM地址設置。LCD內部有一個數據地址指針,用戶可通過它訪問內部全部80字節的數據顯示RAM。

命令格式:80H+地址碼。其中,80H為命令碼。命令9:讀忙標志或地址。BF—忙標志。1:LCD忙,此時LCD不能接受命令或數據;0:表示LCD不忙。命令10:寫數據。命令11:讀數據。例如,將顯示模式設置為“16×2顯示,5×7點陣,8位數據接口”,只需要向1602寫入光標和顯示模式設置命令(命令3)“00111000B”,即38H即可。再如,要求液晶顯示器開顯示,顯示光標且光標閃爍,那么根據顯示開關及光標設置命令(命令4),只要令D=1,C=1和B=1,也就是寫入命令“00001111B”,即0FH,就可實現所需的顯示模式。3.字符顯示位置的確定80字節的DDRAM,與顯示屏上字符顯示位置一一對應,圖5-17給出LCD1602顯示RAM地址與字符顯示位置的對應關系。

當向DDRAM的00H~0FH(第1行)、40H~4FH(第2行)地址的任一處寫數據時,LCD立即顯示出來,該區域也稱為可顯示區域。而當寫入10H~27H或50H~67H地址處時,字符不會顯示出來,該區域也稱為隱藏區域。如果要顯示寫入到隱藏區域的字符,需要通過字符移位命令(命令5)將它們移入到可顯示區域方可正常顯示。需說明的是,在向DDRAM寫入字符時,首先要設置DDRAM定位數據指針,此操作可通過命令8完成。例如,要寫字符到DDRAM的40H處,則命令8的格式為:80H+40H=C0H,其中80H為命令代碼,40H是要寫入字符處的地址。圖5-17LCD內部顯示RAM的地址映射圖4.LCD1602的復位LCD1602上電后復位狀態為:清除屏幕顯示設置為8位數據長度,單行顯示,5×7點陣字符。顯示屏、光標、閃爍功能均關閉。輸入方式為整屏顯示不移動,I/D=1。5.LCD1602基本操作LCD慢顯示器件,所以在寫每條命令前,一定要查詢忙標志位BF,即是否處于“忙”狀態。如LCD正忙于處理其他命令,就等待;如不忙,則向LCD寫入命令。標志位BF連接在8位雙向數據線的D7位上。如果BF=0,表示LCD不忙;如果BF=1,表示LCD處于忙狀態,需等待。LCD1602的讀寫操作規定見表5-4。LCD1602與AT89S51的接口電路見圖5-18。圖5-18

單片機與LCD1602接口電路由圖5-18可看出,LCD1602的RS、R/W*和E這3個引腳分別接在P2.0、P2.1和P2.2引腳,只需通過對這3個引腳置“1”或清“0”,就可實現對LCD1602的讀寫操作。具體來說,顯示一個字符的操作過程為“讀狀態→寫命令→寫數據→自動顯示”。(1)讀狀態是對LCD1602的“忙”標志BF進行檢測,如果BF=1,說明LCD處于忙狀態,不能對其寫命令;如果BF=0,則可寫入命令。

檢測忙標志函數具體如下:77voidcheck_busy(void) //檢查忙標志函數{uchardt;do{dt=0xff; //dt為變量單元,初值為0xffE=0;RS=0; //按照表5-4讀寫操作規定RS=0,E=1時才可讀忙標志RW=1;E=1;dt=out; //out為P0口,P0口的狀態送入dt中

}while(dt&0x80); //如果忙標志BF=1,繼續循環檢測,等待BF=0E=0; //BF=0,LCD不忙,結束檢測}函數檢測P0.7腳電平,即檢測忙標志BF,如BF=1,說明LCD處于忙狀態,不能執行寫命令;BF=0,可執行寫命令。(2)寫命令寫命令函數如下:voidwrite_command(ucharcom) //寫命令函數{ check_busy(); E=0; //按規定RS和E同時為0時可以寫入命令 RS=0; RW=0; out=com; //將命令com寫入P0口 E=1; //按規定寫命令時,E應為正脈沖,即正跳變,所以前面先置E=0 _nop_(); //空操作1個機器周期,等待硬件反應 E=0; //E由高電平變為低電平,LCD開始執行命令 delay(1); //延時,等待硬件響應}79(3)寫數據

將要顯示字符的ASCII碼寫入LCD中的數據顯示RAM(DDRAM),例如將數據“dat”,寫入LCD模塊。寫數據函數如下:voidwrite_data(uchardat) //寫數據函數{ check_busy(); //檢測忙標志BF=1則等待,若BF=0,則可對LCD操作 E=0; //按規定寫數據時,E應為正脈沖,所以先置E=0 RS=1; //按規定RS=1和RW=0時可以寫入數據 RW=0; out=dat; //將數據dat從P0口輸出,即寫入LCD E=1; //E產生正跳變 _nop_(); //空操作,給硬件反應時間 E=0; //E由高變低,寫數據操作結束80

delay(1); }(4)自動顯示數據寫入LCD后,自動讀出字符庫ROM(CGROM)中的字型點陣數據,并自動將字型點陣數據送到液晶顯示屏上顯示。6.LCD1602初始化使用LCD1602前,需對其顯示模式進行初始化設置,初始化函數如下:voidLCD_initial(void) //液晶顯示器初始化函數{ write_command(0x38); //寫命令0x38:兩行顯示,5×7點陣,8位數據_nop_(); //空操作,給硬件反應時間 write_command(0x0C); //寫入命令0x0C:開整體顯示,光標關,無黑塊 _nop_(); //空操作,給硬件反應時間 write_command(0x06); //寫入命令0x06:光標右移 _nop_(); //空操作,給硬件反應時間 write_command(0x01); //寫入命令0x01:清屏 delay(1);}注意:在函數開始處,由于LCD尚未開始工作,所以不需檢測忙標志,但是初始化完成后,每次再寫命令、讀寫數據操作,均需檢測忙標志。825.5.2單片機控制字符型LCD1602顯示案例【例5-9】用單片機驅動字符型液晶顯示器LCD1602,使其顯示兩行文字:“Welcom”與“HarbinCHINA”。見圖5-19。在Proteus中,LCD1602的仿真模型采用LM016L。1.LM016L引腳及特性LM016L的原理符號及引腳見圖5-20。與LCD1602引腳信號相同。引腳功能如下:8384圖5-19

單片機與字符型LCD接口電路與仿真(1)數據線D7~D0;(2)控制線(3根:RS、RW、E);(3)兩根電源線(VDD、VEE)。(4)地線Vss;LM016L的屬性設置見圖5-21,具體如下:(1)每行字符數為16,行數為2;(2)時鐘為250kHz;(3)第1行字符的地址為80H~8FH;(4)第2行字符的地址為C0H~CFH。8586

圖5-20

字符型液晶顯示器LCD引腳圖5-21

字符型液晶顯示器LM016L的屬性設置2.原理電路設計(1)從Proteus庫中選取元器件如下:AT89C51:單片機;LM016L:字符型顯示器;POT-LIN:滑動變阻器;RP1、RP2:排電阻。(2)放置元器件、放置電源和地、連線、元器件屬性設置、電氣檢測所有操作都在ISIS中完成,具體操作見4.6節的介紹。873.C51源程序設計通過KeilμVision3建立工程,再建立源程序“*.c”文件,操作見第4章。在前面介紹的LCD1602基本操作函數的基礎上,不難理解如下源程序。參考程序:#include<reg51.h>#include<intrins.h> //包含_nop_()空函數指令的頭文件#defineucharunsignedchar#defineuintunsignedint#defineoutP0sbitRS=P2^0; //位變量sbitRW=P2^1; //位變量sbitE=P2^2; //位變量voidlcd_initial(void); //LCD初始化函數voidcheck_busy(void); //檢查忙標志函數voidwrite_command(ucharcom); //寫命令函數voidwrite_data(uchardat); //寫數據函數voidstring(ucharad,uchar*s);voidlcd_test(void);voiddelay(uint); //延時函數voidmain(void) //主函數{

lcd_initial(); //調用對LCD初始化函數while(1){ string(0x85,"Welcome"); //顯示的第1行字符串

string(0xC2,"HarbinCHINA"); //顯示的第2行字符串

delay(100); //延時

write_command(0x01); //寫入清屏命令

delay(100); //延時

}}voiddelay(uintj) //1ms延時子程序{ uchari=250; for(;j>0;j--)

90 { while(--i); i=249; while(--i); i=250; }}voidcheck_busy(void)

//檢查忙標志函數{ uchardt; do { dt=0xff; E=0; RS=0; RW=1;91E=1;dt=out;}while(dt&0x80);E=0;}voidwrite_command(ucharcom) //寫命令函數{check_busy();E=0;RS=0;RW=0;out=com;E=1;_nop_();E=0;delay(1);}92voidwrite_data(uchardat)

//寫數據函數{ check_busy(); E=0; RS=1; RW=0; out=dat; E=1; _nop_(); E=0; delay(1); }voidLCD_initial(void)

//液晶顯示器初始化函數{write_command(0x38); //寫入命令0x38:8位兩行顯示,5×7點陣字符write_command(0x0C); //寫入命令0x0C:開整體顯示,光標關,無黑塊write_command(0x06); //寫入命令0x06:光標右移93write_command(0x01); //寫入命令0x01:清屏delay(1);}voidstring(ucharad,uchar*s) //輸出顯示字符串的函數{write_command(ad);while(*s>0){write_data(*s++); //輸出字符串,且指針增1delay(100);}}94最后通過按鈕“Buildtarget”編譯源程序,生成目標代碼“*.hex”文件。若編譯失敗,對程序修改調試直至編譯成功。4.Proteus仿真(1)加載目標代碼文件打開元器件單片機屬性窗口,在“ProgramFile”欄中添加上面編譯好的目標代碼文件“*.hex”;在“ClockFrequency”欄中輸入晶振頻率12MHz。(2)仿真單擊仿真按鈕

啟動仿真,見圖5-19。955.6鍵盤接口設計鍵盤——向單片機輸入數據、命令等功能,是人機對話的主要手段。由若干按鍵按照一定規則組成。每一個按鍵實質上是一個按鍵開關,按構造可分為有觸點開關按鍵和無觸點按鍵。最常用按鍵式鍵盤。下面介紹按鍵式開關鍵盤工作原理、方式以及與鍵盤接口設計與軟件編程。965.6.1鍵盤接口設計應解決的問題1.鍵盤的任務任務3項。(1)判別是否有鍵按下?若有,進入第(2)步。(2)識別哪一個鍵被按下,并求出相應的鍵值。(3)根據鍵值,找到相應鍵值處理程序入口。2.鍵盤輸入特點鍵盤一個按鍵實質就是一個按鍵開關。圖5-22(a)所示按鍵開關的兩端分別連接在行線和列線上,列線接地,行線通過電阻接到+5V上。鍵盤開關機械觸點的斷開、閉合,其行線電壓輸出波形如圖5-22(b)所示。

圖5-22(b)所示的t1和t3分別為鍵的閉合和斷開過程中的抖動期(呈現一串負脈沖),抖動時間長短與開關機械特性有關,一般為5~10ms,t2為穩定的閉合期,其時間由按鍵動作確定,一般為十分之幾秒到幾秒,t0、t4為斷開期。9899圖5-22

鍵盤開關及其行線波形3.按鍵的識別按鍵閉合與否,反應在行線輸出電壓上就是高電平或低電平,對行線電平高低狀態檢測,便可確認按鍵是否按下與松開。為了確保單片機對一次按鍵動作只確認一次按鍵有效,必須消除抖動期t1和t3的影響。4.如何消除按鍵的抖動

常用的按鍵消抖方法有兩種。

(1)通過軟件延時來消抖,基本思想是,在檢測到有鍵按下時,該按鍵所對應的行線為低電平,執行一段延時10ms的子程序后,確認該行線是否仍為低電平,如果仍為低電平,則確認該行確實有鍵按下。當松開按鍵時,行線從低電平變為高電平,執行一段延時10ms的子程序后,檢測到該行線為高電平,說明按鍵確實已經松開。采取以上措施,可消除抖動期t1和t3的影響。100

(2)另一種去除按鍵抖動的方法是采用專用的鍵盤/顯示器接口芯片,這類芯片中都有自動去抖動的硬件電路。鍵盤主要分為兩類:非編碼鍵盤和編碼鍵盤。非編碼鍵盤是利用按鍵直接與單片機相連接而成,常用在按鍵數量較少的場合。該類鍵盤,系統功能比較簡單,需要處理任務較少,成本低、電路設計簡單。按下鍵號的信息通過軟件來獲取。非編碼鍵盤常見的有:獨立式鍵盤和矩陣式鍵盤兩種結構。先介紹獨立式鍵盤接口設計。1015.6.2獨立式鍵盤接口設計案例獨立式鍵盤特點各鍵相互獨立,每個按鍵各接一條I/O口線,通過檢測I/O輸入線的電平狀態,易判斷哪個按鍵被按下。圖5-23為一獨立式鍵盤,8個按鍵k1~k8分別接到單片機的P1.0~P1.7引腳上,圖中上拉電阻保證按鍵未按下時,保證對應I/O口線為穩定高電平。當某一按鍵按下時,對應I/O口線就變成低電平,與其他按鍵相連的I/O口線仍為高電平。因此,只需讀入I/O口線狀態,判別是否為低電平,就很容易識別出哪個鍵被按下??梢姫毩⑹芥I盤優點是電路簡單,各條檢測線獨立,識別按鍵號的軟件編寫簡單。獨立式鍵盤適于按鍵數目較少場合,如按鍵數目較多,要占用較多I/O口線。

102圖5-23

獨立式鍵盤的接口電路1.獨立式鍵盤的查詢工作方式【例5-11】對圖5-23所示獨立式鍵盤,用查詢方式實現鍵盤掃描,根據按下不同按鍵,對其進行處理。掃描程序如下:#include<reg51.h>voidkey_scan(void){ unsignedcharkeyval do { P1=0xff; //P1口為輸入

keyval=P1; //從P1口讀入鍵盤狀態

keyval=~keyval; //鍵盤狀態求反

104switch(keyval) { case1:……; //處理按下的k1鍵,“……”為處理程序 break; //跳出switch語句 case2:……; //處理按下的k2鍵

break; //跳出switch語句 case4:……; //處理按下的k3鍵

break; //跳出switch語句

case8:……; //處理按下的k4鍵

break; //跳出switch語句

case16:……; //處理按下的k5鍵

break; //跳出switch語句

case32:……; //處理按下的k6鍵

break; //跳出switch語句

case64:……; //處理按下的k7鍵

break; //跳出switch語句

case128:……; //處理按下的k8鍵

break; //跳出switch語句

default: break; //無按下鍵處理

}} while(1);}106下面看用Proteus虛擬仿真獨立式鍵盤實際案例。【例5-12】單片機與4個獨立按鍵k1~k4及8個LED指示燈的一個獨立式鍵盤。4個按鍵接在P1.0~P1.3引腳,P3口接8個LED指示燈,控制LED指示燈亮與滅,原理電路見圖5-29。按下k1鍵,P3口8個LED正向(由上至下)流水點亮;

按下k2鍵,P3口8個LED反向(由下而上)流水點亮;按下k3鍵,高、低4個LED交替點亮;

按下k4鍵,P3口8個LED閃爍點亮。圖5-29

虛擬仿真的獨立式鍵盤的接口電路由于本案例中的4個按鍵分別對應4個不同的點亮功能,且具有不同的按鍵值“keyval”,具體如下:按下K1鍵時,keyval=1按下K2鍵時,keyval=2按下K3鍵時,keyval=3按下K4鍵時,keyval=4本獨立式鍵盤工作原理如下:(1)首先判斷是否有按鍵按下。將接有4個按鍵的P1口低4位(P1.0~P1.3)寫入“1”,使P1口低4位為輸入狀態。然后讀入低4位的電平,只要有一位不為“1”,則說明有鍵按下。讀取方法:P1=0xff;if((P1&0x0f)!=0x0f);//讀P1口低4位按鍵值,按位“與”運算后結果非//

0x0f,表明低4位必有1位是“0”,說明有鍵按下(2)按鍵去抖動。當判別有鍵按下時,調用軟件延時子程序,延時約10ms后再進行判別,若按鍵確實按下,則執行相應的按鍵功能,否則重新開始進行掃描。(3)獲得鍵值。確認有鍵按下時,可采用掃描方法,來判哪個鍵按下,并獲取鍵值。110首先KeilμVision3建立工程,再建立源程序“*.c”文件。參考程序:#include<reg51.h>sbitS1=P1^0; //將S1位定義為P1.0引腳sbitS2=P1^1; //將S2位定義為P1.1引腳sbitS3=P1^2; //將S3位定義為P1.2引腳sbitS4=P1^3; //將S4位定義為P1.3引腳unsignedcharkeyval; //定義鍵值儲存變量單元voidmain(void) //主函數{ keyval=0; //鍵值初始化為0 while(1)111{

key_scan(); //調用鍵盤掃描函數

switch(keyval) { case1:forward(); //鍵值為1,調用正向流水點亮函數

break; case2:backward(); //鍵值為2,調用反向流水點亮函數

break; case3:Alter(); //鍵值為3,調用高、低4位交替點亮函數

break; case4:blink(); //鍵值為4,調用閃爍點亮函數

break; } }}112voidkey_scan(void) //函數功能:鍵盤掃描{ P1=0xff;

if((P1&0x0f)!=0x0f) //檢測到有鍵按下

{ delay10ms(); //延時10ms再去檢測

if(S1==0) //按鍵k1被按下

keyval=1; if(S2==0) //按鍵k2被按下

keyval=2; if(S3==0) //按鍵k3被按下

keyval=3; if(S4==0) //按鍵k4被按下

keyval=4; } }113voidforward(void)

溫馨提示

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

評論

0/150

提交評論