51單片機C語言編程實例_第1頁
51單片機C語言編程實例_第2頁
51單片機C語言編程實例_第3頁
51單片機C語言編程實例_第4頁
51單片機C語言編程實例_第5頁
已閱讀5頁,還剩38頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、 電子發(fā)燒友 電子技術(shù)論壇基礎(chǔ)知識:51單片機編程基礎(chǔ)單片機的外部結(jié)構(gòu):1. DIP40雙列直插;2. P0,P1,P2,P3四個8位準(zhǔn)雙向I/O引腳;(作為I/O輸入時,要先輸出高電平)3. 電源 VCC( PIN40)和地線 GND( PIN20);4. 高電平復(fù)位 RESET( PIN9);( 10uF電容接 VCC與RESET,即可實現(xiàn)上電復(fù)位)5. 內(nèi)置振蕩電路,外部只要接晶體至X1( PIN18 )和X0( PIN19 );(頻率為主頻的12倍)6. 程序配置EA( PIN31 )接高電平 VCC;(運行單片機內(nèi)部 ROM中的程序)7. P3 支持第二功能:RXD、TXD、INT0

2、、INT1、TO、T1單片機內(nèi)部I/O部件:(所為學(xué)習(xí)單片機,實際上就是編程控制以下I/O部件,完成指定任務(wù))1. 四個8位通用I/O端口,對應(yīng)引腳 P0、P1、P2和P3;2. 兩個 16 位定時計數(shù)器;(TMOD,TCON,TL0,TH0,TL1,TH1)3. 一個串行通信接口; ( SCON,SBUF)4. 一個中斷控制器;(IE,IP) 針對AT89C52單片機,頭文件 AT89x52.h給出了 SFR特殊功能寄存器所有端口的定義。C語言編程基礎(chǔ):1. 十六進(jìn)制表示字節(jié) 0x5a :二進(jìn)制為 01011010B ; 0x6E為01101110。2. 如果將一個16位二進(jìn)數(shù)賦給一個8位的

3、字節(jié)變量,則自動截斷為低8位,而丟掉咼8位。3. +var表示對變量 var先增一;var 表示對變量后減一。4. x |= 0x0f;表示為 x = x | 0x0f;5. TMOD = ( TMOD & 0xf0 ) | 0x05;表示給變量 TMOD的低四位賦值 0x5,而不改變TMOD的高四位。6. While( 1 );表示無限執(zhí)行該語句,即死循環(huán)。語句后的分號表示空循環(huán)體,也就是;在某引腳輸出高電平的編程方法:(比如P1.3 (PIN4)引腳)代碼1. #include <AT89x52.h> /該頭文檔中有單片機內(nèi)部資源的符號化定義,其中包含P1.32. vo

4、id main(復(fù)位入口3. 4. P1_3 = 1;5. While( 1 );6. void ) /void表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這入單片機運行的/給P1_3賦值1,引腳P1.3就能輸出高電平 VCC/ 死循環(huán),相當(dāng) LOOP: goto LOOP;注意:P0的每個引腳要輸出高電平時,必須外接上拉電阻(如 4K7 )至VCC電源。在某引腳輸出低電平的編程方法:(比如P2.7引腳)代碼1.#include <AT89x52.h> /該頭文檔中有單片機內(nèi)部資源的符號化定義,其中包含P2.72.void main(void )/void表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這

5、入單片機運行的復(fù)位入口3.4.P2_7 = 0;/給P2_7賦值0,弓I腳P2.7就能輸出低電平 GND5.While( 1 );/ 死循環(huán),相當(dāng) LOOP: goto LOOP;6.在某引腳輸出方波編程方法:(比如P3.1引腳)代碼1.#include <AT89x52.h> /該頭文檔中有單片機內(nèi)部資源的符號化定義,其中包含P3.12.void main(void )/void表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這入單片機運行的復(fù)位入口3.4.While( 1 )/非零表示真,如果為真則執(zhí)行下面循環(huán)體的語句5.6.P3_1 = 1;/給P3_1賦值1,引腳P3.1就能輸出高電平

6、VCC7.P3_1 = 0;/給P3_1賦值0,引腳P3.1就能輸出低電平 GND8.II由于一直為真,所以不斷輸岀高、低、高、低;從而形成方波9.將某引腳的輸入電平取反后,從另一個引腳輸出:(比如P0.4 = N0T( P1.1)代碼1. #include <AT89x52.h> /該頭文檔中有單片機內(nèi)部資源的符號化定義,其中包含P0.4和P1.12. void main( void ) /void表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這入單片機運行的復(fù)位入口3. 4. P1_1 = 1;/初始化。P1.1作為輸入,必須輸出高電平5. While( 1 )II非零表示真,如果為真則執(zhí)

7、行下面循環(huán)體的語句6. 7. if ( P1_1 = 1 )8. P0_4 = 0; II讀取P1.1 ,就是認(rèn)為P1.1為輸入,如果P1.1輸入高電平VCC9. elseII否則P1.1輸入為低電平 GNDII給P0_4賦值0,引腳P0.4就能輸出低電平 GND 電子發(fā)燒友 電子技術(shù)論壇 電子發(fā)燒友 電子技術(shù)論壇10. / P0_4 = 0; II給P0_4賦值0,弓I腳P0.4就能輸出低電平 GND11. P0_4 = 1; II給P0_4賦值1,引腳P0.4 就能輸出高電平 VCC12. II由于一直為真,所以不斷根據(jù)P1.1的輸入情況,改變P0.4的輸出電平13. 8個引腳輸出:(比如

8、P2 =將某端口 8個引腳輸入電平,低四位取反后,從另一個端口NOT( P3 )代碼1. #include <AT89x52.h> II該頭文檔中有單片機內(nèi)部資源的符號化定義,其中包含P2和P32.void main位入口i( void )IIvoid表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這入單片機運行的復(fù)3.4.P3 = 0xff;II初始化。P3作為輸入,必須輸出高電平,同時給P3 口的8個引腳輸出高電平5.While( 1 )II非零表示真,如果為真則執(zhí)行下面循環(huán)體的語句6.II取反的方法是異或1,而不取反的方法則是異或07.P2 = P3A0x0fII讀取P3,就是認(rèn)為P3為輸

9、入,低四位異或者 1,即取反,然后輸出8. /由于一直為真,所以不斷將P3取反輸出到P29. 注意:一個字節(jié)的8位D7、D6至DO,分別輸出到 P3.7、P3.6至P3.0,比如P3=0x0f,則 P3.7、P3.6、P3.5、P3.4四個引腳都輸出低電平,而P3.3、P3.2、P3.1、P3.0四個引腳都輸出高電平。同樣,輸入一個端口P2,即是將P2.7、P2.6至P2.0,讀入到一個字節(jié)的8位 D7、D6 至 DO。第一節(jié):單數(shù)碼管按鍵顯示單片機最小系統(tǒng)的硬件原理接線圖:1. 接電源:VCC(PIN40 )、GND( PIN20 )。加接退耦電容 O.luF2. 接晶體:X1( PIN18

10、 )、X2( PIN19 )。注意標(biāo)出晶體頻率(選用 12MHz),還有輔助電容30pF3. 接復(fù)位:RES(PIN9)。接上電復(fù)位電路,以及手動復(fù)位電路,分析復(fù)位工作原理4. 接配置:EA( PIN31 )。說明原因。發(fā)光二極的控制:單片機I/O輸出將一發(fā)光二極管 LED的正極(陽極)接 P1.1,LED的負(fù)極(陰極)接地 GND。只要P1.1 輸出高電平 VCC,LED就正向?qū)ǎ▽?dǎo)通時 LED上的壓降大于1V),有電流流過LED,至 發(fā)LED發(fā)亮。實際上由于P1.1高電平輸出電阻為10K,起到輸出限流的作用, 所以流過LED的電流小于(5V-1V) /10K = 0.4mA。只要P1.1

11、輸出低電平 GND,實際小于0.3V,LED就 不能導(dǎo)通,結(jié)果 LED不亮。開關(guān)雙鍵的輸入:輸入先輸出高一個按鍵 KEY_ON接在P1.6與GND之間,另一個按鍵 KEY_OFF接P1.7與GND之間,按KEY_ON后LED亮,按KEY_OFF后LED滅。同時按下LED半亮,LED保持后松開鍵的狀態(tài),即ON亮OFF滅。代碼1.#include <at89x52.h>2.#define LEDP1A1 /用符號LED代替P1_13.#define KEY_ON P1A6 /用符號 KEY_ON代替P1,_64.#define KEY_OFF P1A7 /用符號KEY_OFF代替P1_

12、75.void main(void )/單片機復(fù)位后的執(zhí)行入口,void 表示空,無輸入?yún)?shù),無返回值6. 7. KEY_0N = 1;/作為輸入,首先輸出高,接下KEY_0N, P1.6則接地為0,否則輸入為18. KEY_0FF = 1;/作為輸入,首先輸出高,接下KEY_0FF,P1.7則接地為0,否則輸入為19. While( 1 )/永遠(yuǎn)為真,所以永遠(yuǎn)循環(huán)執(zhí)行如下括號內(nèi)所有語句10. 11. if ( KEY_ON=0 ) LED=1;/ 是 KEY_ON 接下,所示 P1.1 輸出高,LED 亮12. if ( KEY_OFF=0 ) LED=0;/ 是 KEY_OFF 接下,所示

13、 P1.1 輸出低,LED 滅13. /松開鍵后,都不給 LED賦值,所以LED保持最后按鍵狀態(tài)。14. /同時按下時,LED不斷亮滅,各占一半時間,交替頻率很快,由于人眼慣性,看上去為半亮態(tài)15. 數(shù)碼管的接法和驅(qū)動原理一支七段數(shù)碼管實際由8個發(fā)光二極管構(gòu)成,其中7個組形構(gòu)成數(shù)字8的七段筆畫,所以稱為七段數(shù)碼管,而余下的1個發(fā)光二極管作為小數(shù)點。作為習(xí)慣,分別給 8個發(fā)光二極管標(biāo)上記號:a,b,c,d,e,f,g,h。對應(yīng)8的頂上一畫,按順時針方向排,中間一畫為g,小數(shù)點為h。我們通常又將各二極與一個字節(jié)的8位對應(yīng),a(D0),b(D1),c(D2),d(D3),e(D4),f(D5),g(

14、D6),h(D7),相應(yīng) 8 個發(fā)光二極管正好與單片機一個端口 Pn的8個引腳連接,這樣單片機就可以通過引腳輸出高低電平控制8個發(fā)光二極的亮與滅,從而顯示各種數(shù)字和符號;對應(yīng)字節(jié),引腳接法為:a(Pn.O),b(Pn.1),c(Pn.2),d(Pn.3), e(Pn.4), f(Pn.5), g(Pn.6), h(Pn.7)。如果將8個發(fā)光二極管的負(fù)極(陰極)內(nèi)接在一起,作為數(shù)碼管的一個引腳,這種數(shù)碼 管則被稱為共陰數(shù)碼管,共同的引腳則稱為共陰極,8個正極則為段極。否則,如果是將正極邙日極)內(nèi)接在一起引出的,則稱為共陽數(shù)碼管,共同的引腳則稱為共陽極,8個負(fù)極則為段極。以單支共陰數(shù)碼管為例,可將

15、段極接到某端口Pn,共陰極接GND,則可編寫出對應(yīng)十六進(jìn)制碼的七段碼表字節(jié)數(shù)據(jù)如右圖:顯示宇需共陰機段選碼共陽極段選碼顯示字符共陰根段選碼共陽極段逑碼03FHC0HC39HC6H1F9HD5EHA1H25EHA4HE79H86H34FHB0HF71H34H466H99HF73H32H56DH92HU3EHC1H67DH82Hr31HCEH707HF3Hy6EH91H87FHS0HgFFH00H96FK90H00HFFHA77H8SHB7CHS3H16鍵碼顯示的程序我們在P1端口接一支共陰數(shù)碼管 SLED,在P2、P3端口接16個按鍵,分別編號為KEY_0、 KEY_1到KEY_F,操作時只能按

16、一個鍵,按鍵后SLED顯示對應(yīng)鍵編號。代碼1.#include <at89x52.h>2.#define SLED P13.#define KEY_0 P2A04.#define KEY_1 卩2人15.#define KEY_2 卩2人26.#define KEY_3 卩2人37.#define KEY_4 卩2人48.#define KEY_5 卩2人59.#define KEY_6 卩2人610.#define KEY_7 卩2人711.#define KEY_8 卩3人012.#define KEY_9 卩3人113.#define KEY_A 卩3人214.#define

17、 KEY_B 卩3人315.#define KEY C 卩3人429.if(KEY_0 = 0 ) i=0;if(KEY_1 = 0 ) i=1;30.if(KEY_2 = 0 ) i=2;if(KEY_3 = 0 ) i=3;31.if(KEY_4 = 0 ) i=4;if(KEY_5 = 0 ) i=5;32.if(KEY_6 = 0 ) i=6;if(KEY_7 = 0 ) i=7;33.if(KEY_8 = 0 ) i=8;if(KEY_9 = 0 ) i=9;34.if(KEY_A = 0 ) i=0xA;if ( KEY_B = 0 ) i=0xB;35.if(KEY_C = 0

18、) i=0xC;if ( KEY_D = 0 ) i=0xD;36.if(KEY_E = 0 ) i=0xE;if ( KEY_F = 0 ) i=0xF;28./開始時顯示0,根據(jù)i取應(yīng)七段編碼SLED = Seg7Code i ;37.16.#define KEY_D P3A517. #define KEY_E 卩3人618. #define KEY_F 卩3人719. Code unsigned char Seg7Code16=段編碼字節(jié)/用十六進(jìn)數(shù)作為數(shù)組下標(biāo),可直接取得對應(yīng)的七20./ 0123456789 A b21.0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x

19、6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, Ox7c, 0x39, 0x5e, 0x79, 0x71;22.void main(void23.24.unsignedchari=0;/作為數(shù)組下標(biāo)25.P2 = 0xff;P2作為輸入,初始化輸岀高26.P3 = 0xff;P3作為輸入,初始化輸岀高27.While( 1 )38.39.第二節(jié):雙數(shù)碼管可調(diào)秒表解:只要滿足題目要求,方法越簡單越好。由于單片機I/O資源足夠,所以雙數(shù)碼管可接成靜態(tài)顯示方式,兩個共陰數(shù)碼管分別接在P1 (秒十位)和P2 (秒個位)口,它們的共陰極都接地,安排兩個按鍵接在P3.2 (十位數(shù)調(diào)整)

20、和 P3.3 (個位數(shù)調(diào)整)上,為了方便計時,選用12MHz的晶體。為了達(dá)到精確計時,選用定時器方式2,每計數(shù)250重載一次,即250us, 定義一整數(shù)變量計數(shù)重載次數(shù),這樣計數(shù)4000次即為一秒。定義兩個字節(jié)變量S10和S1分別計算秒十位和秒個位。編得如下程序:代碼1.#include <at89x52.h>2.Code unsignedchar Seg7Code16=/用十六進(jìn)數(shù)作為數(shù)組下標(biāo),可直接取得對應(yīng)的七段編碼字節(jié)3./ 0123456789 A bC d E F4.0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f,

21、 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71;5.void main( void )6.7.unsignedint us250 = 0;8.unsignedchar s10 = 0;9.unsignedchar s1 = 0;10.unsignedchar key10 = 0;/記憶按鍵狀態(tài),為1按下11.unsignedchar key1 = 0;/記憶按鍵狀態(tài),為1按下12./初始化定時器TimerO13.TMOD = (TMOD & 0xF0) | 0x02;14.TH1 = -250;/對于8位二進(jìn)數(shù)來說,-250=6 ,也就是加250次1

22、時為256,即為015.TR1 = 1;16.while (1)/循環(huán)117.P1 = Seg7Code s10 ;/顯示秒十位18.P2 = Seg7Code s1 ;/顯示秒個位19.while ( 1 )/-循環(huán) 220./計時處理21.if ( TF0 = 1 )22.TF0 = 0;23.if ( +us250 >= 4000 )24.us250 = 0;25.if ( +s1 >= 10 )26.s1 = 0;27.if ( +s10 >= 6 ) s10 = 0;28.29.break ; /結(jié)束循環(huán)2”,修改顯示30.31.32./按十位鍵處理33.P3.2

23、= 1;/P3.2作為輸入,先要輸出高電平34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.if ( keylO = 1 )/ 等松鍵if ( P3.2 = 1 ) key10=0;else /未按鍵if ( P3.2 = 0 )key10 = 1;if ( +S10 >= 6 ) s10 = 0;break ; /結(jié)束循環(huán)2”,修改顯示/按個位鍵處理P3.3 = 1;/P3.3 作為輸入,先要輸出高電平if ( key1 = 1 )/ 等松鍵 if ( P3.3 = 1 ) key1=0; else

24、 /未按鍵if ( P3.3 = 0 ) key1 = 1;if ( +s1 >= 10 ) s1 = 0;break ; /結(jié)束循環(huán)2”,修改顯示/ 循環(huán) 2?end / 循環(huán) 1?end main?end第三節(jié):十字路口交通燈如果一個單位時間為 1秒,這里設(shè)定的十字路口交通燈按如下方式四個步驟循環(huán)工作: 60個單位時間,南北紅,東西綠;'10個單位時間,南北紅,東西黃;60個單位時間,南北綠,東西紅;'10個單位時間,南北黃,東西紅;'解:用P1端口的6個引腳控制交通燈,高電平燈亮,低電平燈滅。代碼1.#include <at89x52.h>2./

25、sbit用來定義一個符號位地址,方便編程,提高可讀性,和可移植性3.sbit SNRed =P1A0;/南北方向紅燈4.sbit SNYellow =PM1;/南北方向黃燈5.sbit SNGreen =P1A2;/南北方向綠燈6.sbit EWRed =PM3;/東西方向紅燈7.sbit EWYellow =PM4;/東西方向黃燈8.sbit EWGreen =PM5;/東西方向綠燈9. /*用軟件產(chǎn)生延時一個單位時間*/10. void Delay1Unit( void )11. 12. unsigned int i, j;13. for ( i=0; i<1000; i+ )14.

26、 for ( j<0; j<1000; j+ );/通過實測,調(diào)整j循環(huán)次數(shù),產(chǎn)生1ms延時15. /還可以通過生成匯編程序來計算指令周期數(shù),結(jié)合晶體頻率來調(diào)整j循環(huán)次數(shù),接近1ms16. 17. /* 延時n個單位時間*/18. void Delay( unsignedint n ) for ( ; n!=0; n- ) Delay1Unit(); 19. void main( void )20. 21. while ( 1 )22. 23. SNRed=0; SNYellow=0; SNGreen=1; EWRed=1; EWYellow=0; EWGreen=0; Delay

27、( 60 );24. SNRed=0; SNYellow=1; SNGreen=0; EWRed=1; EWYellow=0; EWGreen=0; Delay( 10 );25. SNRed=1; SNYellow=0; SNGreen=0; EWRed=0; EWYellow=0; EWGreen=1; Delay( 60 );26. SNRed=1; SNYellow=0; SNGreen=0; EWRed=0; EWYellow=1; EWGreen=0; Delay( 10 );27. 28. 第四節(jié):數(shù)碼管驅(qū)動顯示 “12345678'P1端口接8聯(lián)共陰數(shù)碼管SLED8的段

28、極:P1.7接段h,;P1.0接段aP2端口接8聯(lián)共陰數(shù)碼管SLED8的段極:P2.7接左邊的共陰極,P2.0接右邊的共陰極 方案說明:晶振頻率 fosc=12MHz,數(shù)碼管采用動態(tài)刷新方式顯示,在1ms定時斷服務(wù)程序中實現(xiàn)代碼1.#include <at89x92.h>2.unsignedchar DisBuf8;/全局顯示緩沖區(qū),DisBuf0對應(yīng)右SLED , DisBuf7對應(yīng)左SLED,3.void DisplayBrush(void )4. code unsignedcharcathode8=0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f

29、;/陰極控制碼5.Code unsignedchar Seg7Code16=/用十六進(jìn)數(shù)作為數(shù)組下標(biāo),可直接取得對應(yīng)的七段編碼字節(jié)6.0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71;7.static unsignedchari=0;/(0<i <77循環(huán)刷新顯示,由于是靜態(tài)變量,此賦值只做一次。8.P2 = 0xff;/顯示消隱,以免下一段碼值顯示在前一支SLED9.P1 = Seg7Code DisBufi;/從顯示緩沖區(qū)取岀原始數(shù)據(jù),查表變?yōu)槠叨未a后送岀顯示10.P2

30、 = cathode i ;/將對應(yīng)陰極置低,顯示11.if ( +i >= 8 ) i=0;/指向下一個數(shù)碼管和相應(yīng)數(shù)據(jù)12.13.void Timer0lntRoute(void ) interrupt 114.15.TL0 = -1000;/ 由于TL0只有8bits ,所以將(-1000 )低8位賦給TL016.TH0 = (-1000)>>8;/取(-1000 )的高8位賦給TH0,重新定時1ms17.DisplayBrush();18.19.void Timer0Init(void)20. TMOD=(TMOD & 0xf0) | 0x01;/初始化,定時

31、器 T0,工作方式121.TL0 = -1000;/ 定時 1ms22.TH0 = (-1000)>>8;23.TR0 = 1;/允許T0開始計數(shù)24.ET0 = 1;/允許T0計數(shù)溢出時產(chǎn)生中斷請求25.26.void Display( unsignedchar index, unsignedchar dataValue ) DisBufindex = dataValue; 27.void main( void )28.29.unsignedchar i;30.for ( i=0; i<8; i+ ) Display(i, 8-i); DisBuf0為右,DisBuf7為左

32、31.Timer0lnit();32.EA = 1;/允許CPU響應(yīng)中斷請求33.While(1);34.第五節(jié):鍵盤驅(qū)動指提供一些函數(shù)給任務(wù)調(diào)用,獲取按鍵信息,或讀取按鍵值。定義一個頭文檔 <KEY.H>,描述可用函數(shù),如下:代碼1.#ifndef _KEY_H_ /防止重復(fù)引用該文檔,如果沒有定義過符號_KEY_H_,則編譯下面語句2.#define _KEY_H_ /只要引用過一次,即#include <key.h>,則定義符號_KEY_H_3.unsignedchar keyHit(void );/如果按鍵,則返回非0,否則返回04.unsignedchar k

33、eyGet(void );/讀取按鍵值,如果沒有按鍵則等待到按鍵為止5.void keyPut( unsignedchar ucKeyVal );/ 保存按鍵值ucKeyVal到按鍵緩沖隊列末6.void keyBack( unsignedchar ucKeyVal );/ 退回鍵值ucKeyVal到按鍵緩沖隊列首7.#endif定義函數(shù)體文檔KEY.C,如下:代碼1. #include“key.h ”2. #define KeyBufSize 16 /定義按鍵緩沖隊列字節(jié)數(shù)3. unsigned char KeyBuf KeyBufSize ;/定義一個無符號字符數(shù)組作為按鍵緩沖隊列。該隊列

34、為先進(jìn)4. /先出,循環(huán)存取,下標(biāo)從0到 KeyBufSize-15. unsignedchar KeyBufWp=O;/作為數(shù)組下標(biāo)變量,記錄存入位置6. unsignedchar KeyBufRp=0;/作為數(shù)組下標(biāo)變量,記錄讀出位置7. /如果存入位置與讀岀位置相同,則表明隊列中無按鍵數(shù)據(jù)8. unsigned char keyHit( void ) if ( KeyBufWp = KeyBufRp )return ( 0 ); else return ( 1 ); 電子發(fā)燒友 電子技術(shù)論壇10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.2

35、6.27.28.29.30.31.32.33.unsigned char keyGet(void ) unsigned char retVal;/暫存讀岀鍵值while ( keyHit()=O);/等待按鍵,因為函數(shù)keyHit() 的返回值為0表示無按鍵retVal = KeyBuf KeyBufRp ;/從數(shù)組中讀岀鍵值if ( +KeyBufRp >= KeyBufSize ) KeyBufRp=0;/讀位置加1,超岀隊列則循環(huán)回初始位置return ( retVal );void keyPut( unsignedchar ucKeyVal ) KeyBuf KeyBufWp =

36、 ucKeyVal;/鍵值存入數(shù)組if ( +KeyBufWp >= KeyBufSize ) KeyBufWp=0;/存入位置加1,超出隊列則循環(huán)回初始位置/*由于某種原因,讀岀的按鍵,沒有用,但其它任務(wù)要用該按鍵,但傳送又不方便。此時可以退回按鍵隊列。就如取錯了信件,有必要退回一樣*/void keyBack( unsignedchar ucKeyVal )/*如果 KeyBufRp=O; 減 1 后則為 FFH,大于 KeyBufSize,即從數(shù)組頭退回到數(shù)組尾?;蛘哂捎诟蓴_使得KeyBufRp超出隊列位置,也要調(diào)整回到正常位置,*/if ( -KeyBufRp >= Key

37、BufSize ) KeyBufRp=KeyBufSize-1;KeyBuf KeyBufRp = ucKeyVal;/回存鍵值F面漸進(jìn)講解鍵盤物理層的驅(qū)動。電路共同點:P2端口接一共陰數(shù)碼管,共陰極接GND, P2.0接a段、P2.1接b段、P2.7接h段。軟件共同點:code un sig ned char Seg7Code10是七段數(shù)碼管共陰編碼表。 電子發(fā)燒友 電子技術(shù)論壇Code un sig ned char Seg7Code16=/ 0123456789 A b C d E F0x3f, 0x06, 0x5b, Ox4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f

38、, 0x6f, 0x77, 0x7 c, 0x39, 0x5e, 0x79, 0x71;例一:P1.0接一按鍵到GND,鍵編號為,6 ?顯示按鍵。代碼1. #include <at89x52.h>2. #include“KEY.H3. void main( void )4. P1_0 = 1;/作為輸入引腳,必須先輸出高電平5. while ( 1 )/永遠(yuǎn)為真,即死循環(huán)6. if ( P1_0 = 0 )/如果按鍵,則為低電平7. keyPut( 6 );/保存按鍵編號值為按鍵隊列9. 10. if ( keyHit() != 0 )11. P2=Seg7Code keyGet(

39、);8. while ( P1_0 = 0 );/如果一直按著鍵,則不停地執(zhí)行該循環(huán),實際是等待松鍵/如果隊列中有按鍵/從隊列中取岀按鍵值,并顯示在數(shù)碼管上12. 13. 例二:在例一中考慮按鍵 20ms抖動問題。代碼1.#include <at89x52.h>2.#include“KEY.H3.void main(void)4. P1_0 = 1;/作為輸入引腳,必須先輸岀高電平5.while ( 1 )/永遠(yuǎn)為真,即死循環(huán)6. if ( P1_0 =0 )/如果按鍵,則為低電平7. delay20ms();/延時20ms,跳過接下抖動8.keyPut( 6 );/保存按鍵編號值

40、為按鍵隊列9.while ( P1_0=0 );/如果一直按著鍵,則不停地執(zhí)行該循環(huán),實際是等待松鍵10.delay20ms();/延時20ms,跳過松開抖動11.12.if ( keyHit() != 0 )/如果隊列中有按鍵13.P2=Seg7Code keyGet();/從隊列中取岀按鍵值,并顯示在數(shù)碼管上14.15.例三:在例二中考慮干擾問題。即小于20ms的負(fù)脈沖干擾。代碼1. #include <at89x52.h>2. #include“KEY.H3. void main( void )4. P1_0 = 1;/作為輸入引腳,必須先輸出高電平5. while ( 1

41、)/永遠(yuǎn)為真,即死循環(huán)6. if ( P1_0 = 0 )/如果按鍵,則為低電平7. delay20ms();/延時20ms,跳過接下抖動8. if ( P1_0 = 1 )continue ; / 假按鍵9. keyPut( 6 );/保存按鍵編號值為按鍵隊列10. while ( P1_0 = 0 );/如果一直按著鍵,則不停地執(zhí)行該循環(huán),實際是等待松鍵11. delay20ms(); /延時20ms,跳過松開抖動12. 13. if ( keyHit() != 0 )/如果隊列中有按鍵14. P2=Seg7Code keyGet() ;/從隊列中取出按鍵值,并顯示在數(shù)碼管上15. 16.

42、 例四:狀態(tài)圖編程法。通過 20ms周期中斷,掃描按鍵。代碼1 /*2. 采用晶體為12KHz時,指令周期為1ms (即主頻為1KHz ),這樣T0工作在定時器方式位自動重載。計數(shù)值為 20,即可產(chǎn)生20ms的周期性中斷,在中斷服務(wù)程序中實現(xiàn)按鍵掃描3.*/4. #include <at89x52.h>5. #include“KEY.H6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.void main( void )TMOD = ( TMOD & Ox

43、fO ) | 0x02;/不改變T1的工作方式,TO為定時器方式 2TH0 = -20;/計數(shù)周期為20個主頻脈,即20msTL0=TH0;/先軟加載一次計數(shù)值TR0=1;/允許T0開始計數(shù)ET0=1;/允許T0計數(shù)溢出時產(chǎn)生中斷請求EA=1;/允許CPU響應(yīng)中斷請求while ( 1 )/永遠(yuǎn)為真,即死循環(huán)if ( keyHit() != 0 )/如果隊列中有按鍵P2=Seg7Code keyGet() ;/從隊列中取出按鍵值,并顯示在數(shù)碼管上void timer0int(void ) interrupt 1/20ms ; T0 的中斷號為 1 static unsigned char st

44、s=0;P1_0 = 1;/作為輸入引腳,必須先輸出高電平switch ( sts )case 0: if ( P1_0=0 ) sts=1;break ; / 按鍵則轉(zhuǎn)入狀態(tài) 1case 1:if ( P1_0=1 ) sts=0;/假按錯,或干擾,回狀態(tài) 0else sts=2; keyPut( 6 ); /確實按鍵,鍵值入隊列,并轉(zhuǎn)狀態(tài)2break ;case 2: if ( P1_0=1 ) sts=3;break ; / 如果松鍵,則轉(zhuǎn)狀態(tài) 3case 3:if ( P1_0=0 ) sts=2;/ 假松鍵,回狀態(tài) 2else sts=0;/真松鍵,回狀態(tài)0,等待下一次按鍵過程例五:

45、狀態(tài)圖編程法。1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.代碼/*如果采用晶體為12MHz時,指令周期為1us (即主頻為1MHz),要產(chǎn)生20ms左右的計時,則 計數(shù)值達(dá)到20000,TO工作必須為定時器方式 1,16位非自動重載,即可產(chǎn)生 20ms的周期性 中斷,在中斷服務(wù)程序中實現(xiàn)按鍵掃描*/#include <at89x52.h>#include “KEY.Hvoid main( void )TMOD = ( TMOD & OxfO ) | 0

46、x01;/不改變T1的工作方式,T0為定時器方式 1TL0 = -20000;/計數(shù)周期為20000個主頻脈,自動取低 8位TH0 = (-20000)>>8;/右移8位,實際上是取高 8位TR0=1;/允許T0開始計數(shù)ET0=1;/允許T0計數(shù)溢出時產(chǎn)生中斷請求EA=1;/允許CPU響應(yīng)中斷請求while ( 1 )/永遠(yuǎn)為真,即死循環(huán)if ( keyHit() != 0 )/如果隊列中有按鍵P2=Seg7Code keyGet() ;/從隊列中取出按鍵值,并顯示在數(shù)碼管上void timer0int(void ) interrupt 1/20ms ; T0 的中斷號為 1 st

47、atic unsignedchar sts=0;TL0 = -20000;/方式1為軟件重載TH0 = (-20000)>>8;/右移8位,實際上是取高 8位P1_0 = 1;/作為輸入引腳,必須先輸出高電平switch ( sts )case 0: if ( P1_0=0 ) sts=1;break ; / 按鍵則轉(zhuǎn)入狀態(tài) 1case 1:if ( P1_0=1 ) sts=0;/假按錯,或干擾,回狀態(tài) 0else sts=2; keyPut( 6 ); /確實按鍵,鍵值入隊列,并轉(zhuǎn)狀態(tài)2break ;32.case 2:if ( P1_0=1 ) sts=3;break ; /如果松鍵,則轉(zhuǎn)狀態(tài) 333.case 3:34.if ( P1_0=0 ) sts=2;/假松鍵,回狀態(tài)235.elsests=0;/真松鍵,回狀態(tài)0,等待下一次按鍵過程36.37.例六:4X4按鍵。Pl.O(OzE)Pl.l(OxD)P1.2(03fl)Pl. 3(0x7)10FEDCBA9g7654321P 1.4(E) P 1.5(D) Pl 6(B)P 1.7(7)代碼1.*2. 由P1端口的高4位和低4位構(gòu)成4X4的矩陣鍵盤,本程序只認(rèn)為單鍵操作為合法,同時按多 鍵時無效

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論