51單片機(jī)C語言編程基礎(chǔ)及實(shí)例_第1頁
51單片機(jī)C語言編程基礎(chǔ)及實(shí)例_第2頁
51單片機(jī)C語言編程基礎(chǔ)及實(shí)例_第3頁
51單片機(jī)C語言編程基礎(chǔ)及實(shí)例_第4頁
51單片機(jī)C語言編程基礎(chǔ)及實(shí)例_第5頁
已閱讀5頁,還剩26頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、基礎(chǔ)知識(shí):51單片機(jī)編程基礎(chǔ)第一節(jié):單數(shù)碼管按鍵顯示第二節(jié):雙數(shù)碼管可調(diào)秒表第三節(jié):十字路口交通燈第四節(jié):數(shù)碼管驅(qū)動(dòng)第五節(jié):鍵盤驅(qū)動(dòng)第六節(jié):低頻頻率計(jì)第七節(jié):電子表第八節(jié):串行口應(yīng)用基礎(chǔ)知識(shí):51單片機(jī)編程基礎(chǔ)單片機(jī)的外部結(jié)構(gòu):1. DIP40雙列直插; 2. P0,P1,P2,P3四個(gè)8位準(zhǔn)雙向I/O引腳;(作為I/O輸入時(shí),要先輸出高電平) 3. 電源VCC(PIN40)和地線GND(PIN20); 4. 高電平復(fù)位RESET(PIN9);(10uF電容接VCC與RESET,即可實(shí)現(xiàn)上電復(fù)位) 5. 內(nèi)置振蕩電路,外部只要接晶體至X1(PIN18)和X0(PIN19);(頻率為主頻的12倍

2、) 6. 程序配置EA(PIN31)接高電平VCC;(運(yùn)行單片機(jī)內(nèi)部ROM中的程序) 7. P3支持第二功能:RXD、TXD、INT0、INT1、T0、T1 單片機(jī)內(nèi)部I/O部件:(所為學(xué)習(xí)單片機(jī),實(shí)際上就是編程控制以下I/O部件,完成指定任務(wù))1. 四個(gè)8位通用I/O端口,對(duì)應(yīng)引腳P0、P1、P2和P3; 2. 兩個(gè)16位定時(shí)計(jì)數(shù)器;(TMOD,TCON,TL0,TH0,TL1,TH1) 3. 一個(gè)串行通信接口;(SCON,SBUF) 4. 一個(gè)中斷控制器;(IE,IP) 針對(duì)AT89C52單片機(jī),頭文件AT89x52.h給出了SFR特殊功能寄存器所有端口的定義。C語言編程基礎(chǔ):1. 十六進(jìn)

3、制表示字節(jié)0x5a:二進(jìn)制為01011010B;0x6E為01101110。 2. 如果將一個(gè)16位二進(jìn)數(shù)賦給一個(gè)8位的字節(jié)變量,則自動(dòng)截?cái)酁榈?位,而丟掉高8位。 3. +var表示對(duì)變量var先增一;var表示對(duì)變量后減一。 4. x |= 0x0f;表示為 x = x | 0x0f; 5. TMOD = ( TMOD & 0xf0 ) | 0x05;表示給變量TMOD的低四位賦值0x5,而不改變TMOD的高四位。 6. While( 1 ); 表示無限執(zhí)行該語句,即死循環(huán)。語句后的分號(hào)表示空循環(huán)體,也就是; 在某引腳輸出高電平的編程方法:(比如P1.3(PIN4)引腳)代碼1.

4、#include <AT89x52.h> /該頭文檔中有單片機(jī)內(nèi)部資源的符號(hào)化定義,其中包含P1.3    2. void main( void )  /void 表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這入單片機(jī)運(yùn)行的復(fù)位入口    3.    4.  P1_3 = 1;   /給P1_3賦值1,引腳P1.3就能輸出高電平VCC    5.  While(&#

5、160;1 );  /死循環(huán),相當(dāng) LOOP: goto LOOP;    6.    注意:P0的每個(gè)引腳要輸出高電平時(shí),必須外接上拉電阻(如4K7)至VCC電源。在某引腳輸出低電平的編程方法:(比如P2.7引腳)代碼1. #include <AT89x52.h> /該頭文檔中有單片機(jī)內(nèi)部資源的符號(hào)化定義,其中包含P2.7    2. void main( void )  /void 

6、;表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這入單片機(jī)運(yùn)行的復(fù)位入口    3.    4.  P2_7 = 0;   /給P2_7賦值0,引腳P2.7就能輸出低電平GND    5.  While( 1 );  /死循環(huán),相當(dāng) LOOP: goto LOOP;    6.    在某引腳輸出方波編程方法:(比如P3.1引腳)代碼1. #include &

7、lt;AT89x52.h> /該頭文檔中有單片機(jī)內(nèi)部資源的符號(hào)化定義,其中包含P3.1    2. void main( void )  /void 表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這入單片機(jī)運(yùn)行的復(fù)位入口    3.    4.  While( 1 )  /非零表示真,如果為真則執(zhí)行下面循環(huán)體的語句    5.      6. P3_1 =

8、0;1;  /給P3_1賦值1,引腳P3.1就能輸出高電平VCC    7.   P3_1 = 0;  /給P3_1賦值0,引腳P3.1就能輸出低電平GND    8.      /由于一直為真,所以不斷輸出高、低、高、低,從而形成方波    9.    將某引腳的輸入電平取反后,從另一個(gè)引腳輸出:( 比如 P0.4 = NOT( P1.1) )代碼1. #include &l

9、t;AT89x52.h> /該頭文檔中有單片機(jī)內(nèi)部資源的符號(hào)化定義,其中包含P0.4和P1.1    2. void main( void )  /void 表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這入單片機(jī)運(yùn)行的復(fù)位入口    3.    4.  P1_1 = 1;   /初始化。P1.1作為輸入,必須輸出高電平    5. While( 1 ) 

10、0;/非零表示真,如果為真則執(zhí)行下面循環(huán)體的語句    6.      7. if( P1_1 = 1 )  /讀取P1.1,就是認(rèn)為P1.1為輸入,如果P1.1輸入高電平VCC    8.    P0_4 = 0;   /給P0_4賦值0,引腳P0.4就能輸出低電平GND    9.   else    &

11、#160;/否則P1.1輸入為低電平GND    10.   / P0_4 = 0;   /給P0_4賦值0,引腳P0.4就能輸出低電平GND    11.    P0_4 = 1;   /給P0_4賦值1,引腳P0.4就能輸出高電平VCC    12.      /由于一直為真,所以不斷根據(jù)P1.1的輸入情況,改變P0.4的輸

12、出電平    13.    將某端口8個(gè)引腳輸入電平,低四位取反后,從另一個(gè)端口8個(gè)引腳輸出:( 比如 P2 = NOT( P3 ) )代碼1. #include <AT89x52.h> /該頭文檔中有單片機(jī)內(nèi)部資源的符號(hào)化定義,其中包含P2和P3    2. void main( void )  /void 表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這入單片機(jī)運(yùn)行的復(fù)位入口    3.    4.  

13、P3 = 0xff;  /初始化。P3作為輸入,必須輸出高電平,同時(shí)給P3口的8個(gè)引腳輸出高電平    5. While( 1 )  /非零表示真,如果為真則執(zhí)行下面循環(huán)體的語句    6.      /取反的方法是異或1,而不取反的方法則是異或0    7. P2 = P30x0f /讀取P3,就是認(rèn)為P3為輸入,低四位異或者1,即取反,然后輸出    8

14、.      /由于一直為真,所以不斷將P3取反輸出到P2    9.    注意:一個(gè)字節(jié)的8位D7、D6至D0,分別輸出到P3.7、P3.6至P3.0,比如P3=0x0f,則P3.7、P3.6、P3.5、P3.4四個(gè)引腳都輸出低電平,而P3.3、P3.2、P3.1、P3.0四個(gè)引腳都輸出高電平。同樣,輸入一個(gè)端口P2,即是將P2.7、P2.6至P2.0,讀入到一個(gè)字節(jié)的8位D7、D6至D0。共9頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 第一節(jié):單數(shù)碼管按鍵顯示單片機(jī)最小系統(tǒng)的硬件原理接

15、線圖: 1.  接電源:VCC(PIN40)、GND(PIN20)。加接退耦電容0.1uF 2.  接晶體:X1(PIN18)、X2(PIN19)。注意標(biāo)出晶體頻率(選用12MHz),還有輔助電容30pF 3.  接復(fù)位:RES(PIN9)。接上電復(fù)位電路,以及手動(dòng)復(fù)位電路,分析復(fù)位工作原理 4.  接配置:EA(PIN31)。說明原因。 發(fā)光二極的控制:單片機(jī)I/O輸出將一發(fā)光二極管LED的正極(陽極)接P1.1,LED的負(fù)極(陰極)接地GND。只要P1.1輸出高電平VCC,LED就正向?qū)ǎ▽?dǎo)通時(shí)LED上的壓降大于1V),有電流流過LED,至發(fā)LED

16、發(fā)亮。實(shí)際上由于P1.1高電平輸出電阻為10K,起到輸出限流的作用,所以流過LED的電流小于(5V-1V)/10K = 0.4mA。只要P1.1輸出低電平GND,實(shí)際小于0.3V,LED就不能導(dǎo)通,結(jié)果LED不亮。開關(guān)雙鍵的輸入:輸入先輸出高一個(gè)按鍵KEY_ON接在P1.6與GND之間,另一個(gè)按鍵KEY_OFF接P1.7與GND之間,按KEY_ON后LED亮,按KEY_OFF后LED滅。同時(shí)按下LED半亮,LED保持后松開鍵的狀態(tài),即ON亮OFF滅。代碼1. #include <at89x52.h>    2. #define LED

17、0; P11   /用符號(hào)LED代替P1_1    3. #define KEY_ON P16   /用符號(hào)KEY_ON代替P1_6    4. #define KEY_OFF P17   /用符號(hào)KEY_OFF代替P1_7    5. void main( void )    /單片機(jī)復(fù)位后的執(zhí)行入口,void表示空,無輸入?yún)?/p>

18、數(shù),無返回值    6.    7.  KEY_ON = 1;  /作為輸入,首先輸出高,接下KEY_ON,P1.6則接地為0,否則輸入為1    8.  KEY_OFF = 1;  /作為輸入,首先輸出高,接下KEY_OFF,P1.7則接地為0,否則輸入為1    9.  While( 1 )  /永遠(yuǎn)為真,所以永遠(yuǎn)循環(huán)執(zhí)行如下括號(hào)內(nèi)所有語句   

19、; 10.      11.   if( KEY_ON=0 ) LED=1; /是KEY_ON接下,所示P1.1輸出高,LED亮    12.   if( KEY_OFF=0 ) LED=0; /是KEY_OFF接下,所示P1.1輸出低,LED滅    13.   /松開鍵后,都不給LED賦值,所以LED保持最后按鍵狀態(tài)。    14. /同時(shí)按下時(shí),LED不斷亮滅,

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

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

22、   以單支共陰數(shù)碼管為例,可將段極接到某端口Pn,共陰極接GND,則可編寫出對(duì)應(yīng)十六進(jìn)制碼的七段碼表字節(jié)數(shù)據(jù)如右圖: 16鍵碼顯示的程序我們在P1端口接一支共陰數(shù)碼管SLED,在P2、P3端口接16個(gè)按鍵,分別編號(hào)為KEY_0、KEY_1到KEY_F,操作時(shí)只能按一個(gè)鍵,按鍵后SLED顯示對(duì)應(yīng)鍵編號(hào)。代碼1. #include <at89x52.h>    2. #define SLED P1    3. #define KEY_0 P20  

23、0; 4. #define KEY_1 P21    5. #define KEY_2 P22    6. #define KEY_3 P23    7. #define KEY_4 P24    8. #define KEY_5 P25    9. #define KEY_6 P26    10. #define KEY_7 P27 &

24、#160;  11. #define KEY_8 P30    12. #define KEY_9 P31    13. #define KEY_A P32    14. #define KEY_B P33    15. #define KEY_C P34    16. #define KEY_D P35    17. #define K

25、EY_E P36    18. #define KEY_F P37    19. Code unsigned char Seg7Code16= /用十六進(jìn)數(shù)作為數(shù)組下標(biāo),可直接取得對(duì)應(yīng)的七段編碼字節(jié)    20. / 0     1    2     3     4&#

26、160;   5     6     7     8     9    A     b     C     d    E 

27、0;  F    21. 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71;    22. void main( void )    23.    24.  unsign

28、ed char i=0; /作為數(shù)組下標(biāo)    25. P2 = 0xff; /P2作為輸入,初始化輸出高    26.  P3 = 0xff; /P3作為輸入,初始化輸出高    27.  While( 1 )    28.      29.   if( KEY_0 = 0 ) i=0;

29、  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 =

30、60;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;    3

31、4.   if( KEY_A = 0 ) i=0xA;  if( KEY_B = 0 ) i=0xB;    35.   if( KEY_C = 0 ) i=0xC;  if( KEY_D = 0 ) i=0xD;    36.   if( KEY_

32、E = 0 ) i=0xE;  if( KEY_F = 0 ) i=0xF;    37.   SLED = Seg7Code i  /開始時(shí)顯示0,根據(jù)i取應(yīng)七段編碼    38.    39.    共9頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁第二節(jié):雙數(shù)碼管可調(diào)秒表解:只要滿足題目要求,方法越簡單越好。由于單片機(jī)I/

33、O資源足夠,所以雙數(shù)碼管可接成靜態(tài)顯示方式,兩個(gè)共陰數(shù)碼管分別接在P1(秒十位)和P2(秒個(gè)位)口,它們的共陰極都接地,安排兩個(gè)按鍵接在P3.2(十位數(shù)調(diào)整)和P3.3(個(gè)位數(shù)調(diào)整)上,為了方便計(jì)時(shí),選用12MHz的晶體。為了達(dá)到精確計(jì)時(shí),選用定時(shí)器方式2,每計(jì)數(shù)250重載一次,即250us,定義一整數(shù)變量計(jì)數(shù)重載次數(shù),這樣計(jì)數(shù)4000次即為一秒。定義兩個(gè)字節(jié)變量S10和S1分別計(jì)算秒十位和秒個(gè)位。編得如下程序:代碼1. #include <at89x52.h>    2. Code unsigned char Seg7C

34、ode16= /用十六進(jìn)數(shù)作為數(shù)組下標(biāo),可直接取得對(duì)應(yīng)的七段編碼字節(jié)    3. / 0     1    2     3     4    5     6     7     8

35、     9    A     b     C     d    E    F    4. 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,&#

36、160;0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71;    5. void main( void )    6.    7.  unsigned int us250 = 0;    8.  unsigned char s10 = 0;    9. &

37、#160;unsigned char s1 = 0;    10.  unsigned char key10 = 0; /記憶按鍵狀態(tài),為1按下    11.  unsigned char key1 = 0;  /記憶按鍵狀態(tài),為1按下    12.  /初始化定時(shí)器 Timer0    13.  TMOD 

38、= (TMOD & 0xF0) | 0x02;    14.  TH1 = -250; /對(duì)于8位二進(jìn)數(shù)來說,-250=6,也就是加250次1時(shí)為256,即為0    15.  TR1 = 1;    16.  while(1)           /-循環(huán)1    17

39、.   P1 = Seg7Code s10  /顯示秒十位    18.   P2 = Seg7Code s1  /顯示秒個(gè)位    19.   while( 1 )         /-循環(huán)2    20.    /計(jì)時(shí)處理  

40、  21. if( TF0 = 1 )    22.     TF0 = 0;    23.     if( +us250 >= 4000 )    24.      us250 = 0;    25.     &

41、#160;if( +s1 >= 10 )    26.       s1 = 0;    27.       if( +s10 >= 6 ) s10 = 0;    28.          29. 

42、0;    break; /結(jié)束“循環(huán)2”,修改顯示    30.         31.        32.    /按十位鍵處理    33.    P3.2 = 1;  /P3.2作為輸入,先要輸出高電平    34.    if( 

43、;key10 = 1 ) /等松鍵    35.  if( P3.2 = 1 ) key10=0;    36.        37. else   /未按鍵    38.     if( P3.2 = 0 )    39.    

44、;  key10 = 1;    40.  if( +s10 >= 6 ) s10 = 0;    41.      break; /結(jié)束“循環(huán)2”,修改顯示    42.         43.        44.   

45、 /按個(gè)位鍵處理    45.    P3.3 = 1;  /P3.3作為輸入,先要輸出高電平    46.    if( key1 = 1 ) /等松鍵    47.  if( P3.3 = 1 ) key1=0;     48.    else 

46、   /未按鍵    49.     if( P3.3 = 0 ) key1 = 1;    50.  if( +s1 >= 10 ) s1 = 0;    51.      break; /結(jié)束“循環(huán)2”,修改顯示    52. &

47、#160;       53.        54.    /循環(huán)2end    55.   /循環(huán)1end    56. /mainend   共9頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 第三節(jié):十字路口交通燈如果一個(gè)單位時(shí)間為1秒,這里設(shè)定的十字路口交通燈按如下方式四個(gè)步驟循環(huán)工作: 60個(gè)單位時(shí)間,南北紅,東西綠;l 10個(gè)單位時(shí)間,南北紅,東

48、西黃;l 60個(gè)單位時(shí)間,南北綠,東西紅;l 10個(gè)單位時(shí)間,南北黃,東西紅;l解:用P1端口的6個(gè)引腳控制交通燈,高電平燈亮,低電平燈滅。代碼1. #include <at89x52.h>    2. /sbit用來定義一個(gè)符號(hào)位地址,方便編程,提高可讀性,和可移植性    3. sbit SNRed =P10;  /南北方向紅燈    4. sbit SNYellow =P11;  /南北方向黃燈  

49、  5. sbit SNGreen =P12;  /南北方向綠燈    6. sbit EWRed =P13;  /東西方向紅燈    7. sbit EWYellow =P14;  /東西方向黃燈    8. sbit EWGreen =P15;  /東西方向綠燈    9. /* 用軟件產(chǎn)生延時(shí)一個(gè)單位時(shí)間 */ 

50、  10. void Delay1Unit( void )       11.    12.  unsigned int i, j;    13.  for( i=0; i<1000; i+ )     14.   for( j<0; j<1000; j+ ); 

51、;/通過實(shí)測,調(diào)整j循環(huán)次數(shù),產(chǎn)生1ms延時(shí)    15. /還可以通過生成匯編程序來計(jì)算指令周期數(shù),結(jié)合晶體頻率來調(diào)整j循環(huán)次數(shù),接近1ms    16.    17. /* 延時(shí)n個(gè)單位時(shí)間 */   18. void Delay( unsigned int n ) for(  n!=0; n- ) Delay1Unit();     19. void&

52、#160;main( void )    20.    21.  while( 1 )    22.       23.   SNRed=0; SNYellow=0; SNGreen=1; EWRed=1; EWYellow=0; EWGreen=0; Delay( 60 );    24.   SNRed=

53、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; 

54、SNYellow=0; SNGreen=0; EWRed=0; EWYellow=1; EWGreen=0; Delay( 10 );    27.      28.    共9頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁第四節(jié):數(shù)碼管驅(qū)動(dòng)顯示“12345678”P1端口接8聯(lián)共陰數(shù)碼管SLED8的段極:P1.7接段h,,P1.0接段aP2端口接8聯(lián)共陰數(shù)碼管SLED8的段極:P2.7接左邊的共陰極,P2.0接右邊的共陰極方案說明:晶振頻率fo

55、sc=12MHz,數(shù)碼管采用動(dòng)態(tài)刷新方式顯示,在1ms定時(shí)斷服務(wù)程序中實(shí)現(xiàn)代碼1. #include <at89x92.h>    2. unsigned char DisBuf8;  /全局顯示緩沖區(qū),DisBuf0對(duì)應(yīng)右SLED,DisBuf7對(duì)應(yīng)左SLED,    3. void DisplayBrush( void )    4.  code unsigned char cathode8=0xfe

56、,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f; /陰極控制碼    5. Code unsigned char Seg7Code16= /用十六進(jìn)數(shù)作為數(shù)組下標(biāo),可直接取得對(duì)應(yīng)的七段編碼字節(jié)    6. 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71;    7. static unsigned char i=0;

57、60;/ (0i7) 循環(huán)刷新顯示,由于是靜態(tài)變量,此賦值只做一次。    8.  P2 = 0xff;  /顯示消隱,以免下一段碼值顯示在前一支SLED    9.  P1 = Seg7Code DisBufi  /從顯示緩沖區(qū)取出原始數(shù)據(jù),查表變?yōu)槠叨未a后送出顯示    10. P2 = cathode i    /將對(duì)應(yīng)陰極置低,顯

58、示    11. if( +i >= 8 ) i=0;  /指向下一個(gè)數(shù)碼管和相應(yīng)數(shù)據(jù)    12.    13. void Timer0IntRoute( void ) interrupt 1    14.    15.  TL0 = -1000;  /由于TL0只有8bits,所以將(-1000)低8位賦給TL0 &#

59、160;  16.  TH0 = (-1000)>>8; /取(-1000)的高8位賦給TH0,重新定時(shí)1ms    17.  DisplayBrush();    18.    19. void Timer0Init( void )    20.  TMOD=(TMOD & 0xf0) | 0x01; /初始化,定時(shí)器T0,工作方式1  

60、;  21.  TL0 = -1000; /定時(shí)1ms    22.  TH0 = (-1000)>>8;    23.  TR0 = 1;   /允許T0開始計(jì)數(shù)    24.  ET0 = 1;   /允許T0計(jì)數(shù)溢出時(shí)產(chǎn)生中斷請求    25.    26. void D

61、isplay( unsigned char index, unsigned char dataValue ) DisBuf index  = dataValue;     27. void main( void )    28.    29. unsigned char i;    30. for( i=0; i<

62、;8; i+ ) Display(i, 8-i);  /DisBuf0為右,DisBuf7為左    31. Timer0Init();    32. EA = 1;   /允許CPU響應(yīng)中斷請求    33. While(1);    34.    共9頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 第五節(jié):鍵盤驅(qū)動(dòng)指提供一些函數(shù)給任務(wù)調(diào)用,獲取按鍵信息,或讀取按鍵值。定義一

63、個(gè)頭文檔 <KEY.H>,描述可用函數(shù),如下:代碼1. #ifndef _KEY_H_  /防止重復(fù)引用該文檔,如果沒有定義過符號(hào) _KEY_H_,則編譯下面語句    2. #define _KEY_H_  /只要引用過一次,即 #include <key.h>,則定義符號(hào) _KEY_H_    3. unsigned char keyHit( void ); /如果按鍵,則返回非

64、,否則返回    4. unsigned char keyGet( void ); /讀取按鍵值,如果沒有按鍵則等待到按鍵為止    5. void keyPut( unsigned char ucKeyVal ); /保存按鍵值ucKeyVal到按鍵緩沖隊(duì)列末    6. void keyBack( unsigned char ucKeyVal ); /退回鍵值uc

65、KeyVal到按鍵緩沖隊(duì)列首    7. #endif   定義函數(shù)體文檔 KEY.C,如下:代碼1. #include “key.h”    2. #define KeyBufSize 16 /定義按鍵緩沖隊(duì)列字節(jié)數(shù)    3. unsigned char KeyBuf KeyBufSize  /定義一個(gè)無符號(hào)字符數(shù)組作為按鍵緩沖隊(duì)列。該隊(duì)列為先進(jìn)    4.    

66、0;    /先出,循環(huán)存取,下標(biāo)從到 KeyBufSize-1    5. unsigned char KeyBufWp=0; /作為數(shù)組下標(biāo)變量,記錄存入位置    6. unsigned char KeyBufRp=0; /作為數(shù)組下標(biāo)變量,記錄讀出位置    7. /如果存入位置與讀出位置相同,則表明隊(duì)列中無按鍵數(shù)據(jù)    8. unsigned char keyHit(

67、0;void )    9.  if( KeyBufWp = KeyBufRp ) return( 0 ); else return( 1 );     10.    11. unsigned char keyGet( void )    12.  unsigned char retVal; /暫存

68、讀出鍵值    13. while( keyHit()=0 ); /等待按鍵,因?yàn)楹瘮?shù)keyHit()的返回值為 0 表示無按鍵    14. retVal = KeyBuf KeyBufRp  /從數(shù)組中讀出鍵值    15. if( +KeyBufRp >= KeyBufSize ) KeyBufRp=0; /讀位置加,超出隊(duì)列則循環(huán)回初始位置   

69、; 16.  return( retVal );    17.    18.    19. void keyPut( unsigned char ucKeyVal )    20.  KeyBuf KeyBufWp  = ucKeyVal; /鍵值存入數(shù)組    21.  if( +KeyBufWp >= Key

70、BufSize ) KeyBufWp=0;  /存入位置加,超出隊(duì)列則循環(huán)回初始位置    22.    23. /*   24. 由于某種原因,讀出的按鍵,沒有用,但其它任務(wù)要用該按鍵,但傳送又不方便。此時(shí)可以退回按鍵隊(duì)列。就如取錯(cuò)了信件,有必要退回一樣   25. */   26. void keyBack( unsigned char ucKeyVal )    27.    28

71、. /*   29. 如果KeyBufRp=0; 減1后則為FFH,大于KeyBufSize,即從數(shù)組頭退回到數(shù)組尾。或者由于干擾使得KeyBufRp超出隊(duì)列位置,也要調(diào)整回到正常位置,   30. */   31.  if( -KeyBufRp >= KeyBufSize ) KeyBufRp=KeyBufSize-1;     32. KeyBuf KeyBufRp  = ucKeyVal; /回

72、存鍵值    33.    下面漸進(jìn)講解鍵盤物理層的驅(qū)動(dòng)。電路共同點(diǎn):P2端口接一共陰數(shù)碼管,共陰極接GND,P2.0接a段、P2.1接b段、P2.7接h段。軟件共同點(diǎn):code unsigned char Seg7Code10 是七段數(shù)碼管共陰編碼表。Code unsigned char Seg7Code16=/ 0     1    2     3     4    5&#

73、160;    6     7     8     9    A     b     C     d    E    F0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f,

74、0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71;例一:P1.0接一按鍵到GND,鍵編號(hào)為,顯示按鍵。代碼1. #include <at89x52.h>    2. #include “KEY.H”    3. void main( void )    4.  P1_0 = 1;  /作為輸入引腳,必須先輸出高電平    5. while( 1 ) /永遠(yuǎn)

75、為真,即死循環(huán)    6.   if( P1_0 = 0 ) /如果按鍵,則為低電平    7.  keyPut( 6 ); /保存按鍵編號(hào)值為按鍵隊(duì)列    8. while( P1_0 = 0 ); /如果一直按著鍵,則不停地執(zhí)行該循環(huán),實(shí)際是等待松鍵    9.       10. if( keyHit

76、() != 0 ) /如果隊(duì)列中有按鍵    11. P2=Seg7Code keyGet()  /從隊(duì)列中取出按鍵值,并顯示在數(shù)碼管上    12.      13.    例二:在例一中考慮按鍵20ms抖動(dòng)問題。代碼1. #include <at89x52.h>    2. #include “KEY.H”    3. void main( 

77、void )    4.  P1_0 = 1;  /作為輸入引腳,必須先輸出高電平    5. while( 1 ) /永遠(yuǎn)為真,即死循環(huán)    6.   if( P1_0 = 0 ) /如果按鍵,則為低電平    7.  delay20ms(); /延時(shí)20ms,跳過接下抖動(dòng)    8. keyPut( 6

78、 ); /保存按鍵編號(hào)值為按鍵隊(duì)列    9.  while( P1_0 = 0 ); /如果一直按著鍵,則不停地執(zhí)行該循環(huán),實(shí)際是等待松鍵    10. delay20ms(); /延時(shí)20ms,跳過松開抖動(dòng)    11.       12. if( keyHit() != 0 ) /如果隊(duì)列中有按鍵    13. P2=Seg7Cod

79、e keyGet()  /從隊(duì)列中取出按鍵值,并顯示在數(shù)碼管上    14.      15.    例三:在例二中考慮干擾問題。即小于20ms的負(fù)脈沖干擾。代碼1. #include <at89x52.h>    2. #include “KEY.H”    3. void main( void )    4.  P1_0 = 1; 

80、 /作為輸入引腳,必須先輸出高電平    5. while( 1 ) /永遠(yuǎn)為真,即死循環(huán)    6.   if( P1_0 = 0 ) /如果按鍵,則為低電平    7.  delay20ms(); /延時(shí)20ms,跳過接下抖動(dòng)    8.  if( P1_0 = 1 ) continue; /假按鍵  &

81、#160; 9. keyPut( 6 ); /保存按鍵編號(hào)值為按鍵隊(duì)列    10.  while( P1_0 = 0 ); /如果一直按著鍵,則不停地執(zhí)行該循環(huán),實(shí)際是等待松鍵    11. delay20ms(); /延時(shí)20ms,跳過松開抖動(dòng)    12.       13. if( keyHit() != 0 ) /如果隊(duì)列中有按鍵 

82、60;  14. P2=Seg7Code keyGet()  /從隊(duì)列中取出按鍵值,并顯示在數(shù)碼管上    15.      16.    例四:狀態(tài)圖編程法。通過20ms周期中斷,掃描按鍵。代碼1. /*   2. 采用晶體為12KHz時(shí),指令周期為1ms(即主頻為1KHz),這樣T0工作在定時(shí)器方式2,8位自動(dòng)重載。計(jì)數(shù)值為20,即可產(chǎn)生20ms的周期性中斷,在中斷服務(wù)程序中實(shí)現(xiàn)按鍵掃描   3. */   4. #include 

83、<at89x52.h>    5. #include “KEY.H”    6. void main( void )    7.      8. TMOD = (TMOD & 0xf0 ) | 0x02; /不改變T1的工作方式,T0為定時(shí)器方式2    9. TH0 = -20;    

84、 /計(jì)數(shù)周期為20個(gè)主頻脈,即20ms    10. TL0=TH0;      /先軟加載一次計(jì)數(shù)值    11. TR0=1;      /允許T0開始計(jì)數(shù)    12. ET0=1;      /允許T0計(jì)數(shù)溢出時(shí)產(chǎn)生中斷請求    13. EA=1;      

85、/允許CPU響應(yīng)中斷請求    14. while( 1 ) /永遠(yuǎn)為真,即死循環(huán)    15.      16. if( keyHit() != 0 ) /如果隊(duì)列中有按鍵    17. P2=Seg7Code keyGet()  /從隊(duì)列中取出按鍵值,并顯示在數(shù)碼管上    18.      19.    20. void&

86、#160;timer0int( void ) interrupt 1 /20ms;T0的中斷號(hào)為1    21.  static unsigned char sts=0;    22.  P1_0 = 1;  /作為輸入引腳,必須先輸出高電平    23. switch( sts )    24.      25.  

87、 case 0: if( P1_0=0 ) sts=1; break; /按鍵則轉(zhuǎn)入狀態(tài)1    26.   case 1:    27. if( P1_0=1 ) sts=0;  /假按錯(cuò),或干擾,回狀態(tài)0    28. else sts=2; keyPut( 6 );  /確實(shí)按鍵,鍵值入隊(duì)列,并轉(zhuǎn)狀態(tài)2 

88、0;  29. break;    30.   case 2: if( P1_0=1 ) sts=3; break; /如果松鍵,則轉(zhuǎn)狀態(tài)3    31.   case 3:    32.    if( P1_0=0 ) sts=2;  /假松鍵,回狀態(tài)2    33.    e

89、lse sts=0;    /真松鍵,回狀態(tài)0,等待下一次按鍵過程     34.      35.     例五:狀態(tài)圖編程法。代碼1. /*   2. 如果采用晶體為12MHz時(shí),指令周期為1us(即主頻為1MHz),要產(chǎn)生20ms左右的計(jì)時(shí),則計(jì)數(shù)值達(dá)到20000,T0工作必須為定時(shí)器方式1,16位非自動(dòng)重載,即可產(chǎn)生20ms的周期性中斷,在中斷服務(wù)程序中實(shí)現(xiàn)按鍵掃描   3. */   4. #include

90、 <at89x52.h>    5. #include “KEY.H”    6. void main( void )    7.      8. TMOD = (TMOD & 0xf0 ) | 0x01; /不改變T1的工作方式,T0為定時(shí)器方式1    9. TL0 = -20000;  

91、60;  /計(jì)數(shù)周期為20000個(gè)主頻脈,自動(dòng)取低8位    10. TH0 = (-20000)>>8;    /右移8位,實(shí)際上是取高8位    11. TR0=1;      /允許T0開始計(jì)數(shù)    12. ET0=1;      /允許T0計(jì)數(shù)溢出時(shí)產(chǎn)生中斷請求    13. EA=1; 

92、;     /允許CPU響應(yīng)中斷請求    14. while( 1 ) /永遠(yuǎn)為真,即死循環(huán)    15.      16. if( keyHit() != 0 ) /如果隊(duì)列中有按鍵    17. P2=Seg7Code keyGet()  /從隊(duì)列中取出按鍵值,并顯示在數(shù)碼管上    18.    &#

93、160; 19.    20. void timer0int( void ) interrupt 1 /20ms;T0的中斷號(hào)為1    21.  static unsigned char sts=0;    22. TL0 = -20000;     /方式1為軟件重載    23. TH0 = (-20000)>>8;    /右移8位,實(shí)際上是取高8位    24.  P1_0 = 1;  /作為輸入引腳,必須先輸出高電平    25. switch( sts )    26.      27.   case 0: if( P1_0=

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論