![51單片機(jī)C語言學(xué)習(xí)資料_第1頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/17/b432600e-1bc1-4a54-8c64-5f7d5af9372c/b432600e-1bc1-4a54-8c64-5f7d5af9372c1.gif)
![51單片機(jī)C語言學(xué)習(xí)資料_第2頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/17/b432600e-1bc1-4a54-8c64-5f7d5af9372c/b432600e-1bc1-4a54-8c64-5f7d5af9372c2.gif)
![51單片機(jī)C語言學(xué)習(xí)資料_第3頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/17/b432600e-1bc1-4a54-8c64-5f7d5af9372c/b432600e-1bc1-4a54-8c64-5f7d5af9372c3.gif)
![51單片機(jī)C語言學(xué)習(xí)資料_第4頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/17/b432600e-1bc1-4a54-8c64-5f7d5af9372c/b432600e-1bc1-4a54-8c64-5f7d5af9372c4.gif)
![51單片機(jī)C語言學(xué)習(xí)資料_第5頁](http://file2.renrendoc.com/fileroot_temp3/2021-11/17/b432600e-1bc1-4a54-8c64-5f7d5af9372c/b432600e-1bc1-4a54-8c64-5f7d5af9372c5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、51單片機(jī)C語言學(xué)習(xí)資料目 錄前言 錯誤! 未定義書簽基礎(chǔ)知識:單片機(jī)編程基礎(chǔ) 2第一節(jié):單數(shù)碼管按鍵顯示 4第二節(jié):雙數(shù)碼管可調(diào)秒表 6第三節(jié):十字路口交通燈 6第四節(jié):數(shù)碼管驅(qū)動 8第五節(jié):鍵盤驅(qū)動 9第六節(jié):低頻頻率計 15第七節(jié):電子表 18第八節(jié):串行口應(yīng)用 19基礎(chǔ)知識:單片機(jī)編程基礎(chǔ)單片機(jī)的外部結(jié)構(gòu):1、DIP40雙列直插;2、 P0, P1, P2, P3四個8位準(zhǔn)雙向I/O弓I腳;(作為I/O輸入時,要先輸出高電平)3、電源 VCC( PIN40)和地線 GND( PIN20);4、 高電平復(fù)位RESET( PIN9); ( 10uF電容接VC勇 RESET即可實現(xiàn)上電復(fù)位)
2、5、 內(nèi)置振蕩電路,外部只要接晶體至X1 (PIN18)和X0 (PIN19);(頻率為主頻的12倍)6、程序配置EA (PIN31)接高電平VCC (運(yùn)行單片機(jī)內(nèi)部 RO附的程序)7、P3 支持第二功能:RXD TXD INT0、INT1、T0、T1單片機(jī)內(nèi)部I/O部件:(所為學(xué)習(xí)單片機(jī),實際上就是編程控制以下I/O部件,完成指定任務(wù))1、 四個8位通用I/O端口,對應(yīng)引腳 P0、P1、P2和P3;2、 兩個 16 位定時計數(shù)器;(TMOD TCON TL0, TH0, TL1, TH1)3、一個串行通信接口; (SCON SBUF4、 一個中斷控制器;(IE , IP)針對AT89C52單
3、片機(jī),頭文件 AT89x52.h給出了 SFR特殊功能寄存器所有端口的定義。教科書的160頁給出了針對MCS51系列單片機(jī)的C語言擴(kuò)展變量類型。C語言編程基礎(chǔ):1、 十六進(jìn)制表示字節(jié) 0x5a:二進(jìn)制為 01011010B; 0x6E為01101110。2、 如果將一個16位二進(jìn)數(shù)賦給一個8位的字節(jié)變量,則自動截斷為低8位,而丟掉高8位。3、 +var表示對變量 var先增一;var 表示對變量后減一。4、 x |= 0x0f; 表示為 x = x | 0x0f;5、 TMOD = ( TMOD & 0xf0 ) | 0x05;表示給變量 TMOD勺低四位賦值 0x5,而不改變 TMO
4、D勺高四位。6、 While( 1 );表示無限執(zhí)行該語句,即死循環(huán)。語句后的分號表示空循環(huán)體,也就是 ;在某引腳輸出高電平的編程方法:(比如P1.3 (PIN4)引腳)#include <AT89x52.h>/該頭文檔中有單片機(jī)內(nèi)部資源的符號化定義,其中包含P1.3void main( void )/void表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這入單片機(jī)運(yùn)行的復(fù)位入口P1_3 = 1;/給P1_3賦值1,引腳P1.3就能輸出高電平 VCCWhile( 1 );/ 死循環(huán),相當(dāng) LOOP: goto LOOP;注意:P0的每個引腳要輸出高電平時,必須外接上拉電阻(如4K70至VCOt
5、源在某引腳輸出低電平的編程方法:(比如P2.7引腳)#include <AT89x52.h>/該頭文檔中有單片機(jī)內(nèi)部資源的符號化定義,其中包含 P2.7void main( void )/void表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這入單片機(jī)運(yùn)行的復(fù)位入口P2_7 = 0;/給P2_7賦值0,引腳P2.7就能輸出低電平 GNDWhile( 1 );/ 死循環(huán),相當(dāng) LOOP: goto LOOP;)在某引腳輸出方波編程方法:(比如P3.1引腳)#include <AT89x52.h>/該頭文檔中有單片機(jī)內(nèi)部資源的符號化定義,其中包含 P3.1void main( void
6、 )/void 表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這入單片機(jī)運(yùn)行的復(fù)位入口While( 1 )/非零表示真,如果為真則執(zhí)行下面循環(huán)體的語句P3_1 = 1;/給P3_1賦值1,引腳P3.1就能輸出高電平 VCCP3_1 = 0;/給P3_1賦值0,引腳P3.1就能輸出低電平 GND)/由于一直為真,所以不斷輸出高、低、高、低,從而形成方波)將某引腳的輸入電平取反后,從另一個引腳輸出:(比如P0.4 = NOT( P1.1)#include <AT89x52.h>/該頭文檔中有單片機(jī)內(nèi)部資源的符號化定義,其中包含 P0.4和P1.1void main( void )/void表示沒有
7、輸入?yún)?shù),也沒有函數(shù)返值,這入單片機(jī)運(yùn)行的復(fù)位入口P1_1 = 1;/初始化。P1.1作為輸入,必須輸出高電平While( 1 )/非零表示真,如果為真則執(zhí)行下面循環(huán)體的語句if(P1_1 =1)P0_4=0;else/P0_4=0;P0_4=1;/讀取P1.1,就是認(rèn)為P1.1為輸入,如果P1.1輸入高電平VCC)/給P0_4賦值0,引腳P0.4就能輸出低電平 GND/否則P1.1輸入為低電平GND)/給P0_4賦值0,引腳P0.4就能輸出低電平 GND)/給P0_4賦值1,引腳P0.4就能輸出高電平 VCC/由于一直為真,所以不斷根據(jù)P1.1的輸入情況,改變 P0.4的輸出電平8個引腳輸出
8、:(比如P2 = NOT( P3 )將某端口 8個引腳輸入電平,低四位取反后,從另一個端口#include <AT89x52.h>/該頭文檔中有單片機(jī)內(nèi)部資源的符號化定義,其中包含 P2和P3void main( void )/void表示沒有輸入?yún)?shù),也沒有函數(shù)返值,這入單片機(jī)運(yùn)行的復(fù)位入口P3 = 0xff;/初始化。P3作為輸入,必須輸出高電平,同時給 P3 口的8個引腳輸出高電平While( 1 )/非零表示真,如果為真則執(zhí)行下面循環(huán)體的語句/取反的方法是異或1,而不取反的方法則是異或0P2 = P3A0x0f/讀取P3,就是認(rèn)為P3為輸入,低四位異或者1,即取反,然后輸出
9、)/由于一直為真,所以不斷將P3取反輸出到P2注意:一個字節(jié)的8位DX D6至D0,分另U輸出至U P3.7、P3.6至P3.0,比如P3=0x0f,貝U 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至D0。第一節(jié):單數(shù)碼管按鍵顯示單片機(jī)最小系統(tǒng)的硬件原理接線圖:1、接電源:VCC( PIN40)、GND( PIN20)。加接退耦電容 0.1uF2、接晶體:X1 (PIN18)、X2 (PIN19)。注意標(biāo)出晶體頻率(選用 1
10、2MH0,還有輔助電容30pF3、接復(fù)位:RES( PIN9)。接上電復(fù)位電路,以及手動復(fù)位電路,分析復(fù)位工作原理4、接配置:EA (PIN31 )。說明原因。發(fā)光二極的控控制:單片機(jī) I/O輸出將一發(fā)光二極管LED的正極(陽極)接 P1.1 , LED的負(fù)極(陰極)接地 GND只要P1.1輸出高電平VCCLED就正向?qū)?導(dǎo)通時 LED上的壓降大于1V),有電流流過LED至發(fā)LED發(fā)亮。實際上由于 P1.1高電 平輸出電阻為10K,起到輸出限流的作用,所以流過 LED的電流小于(5V-1V) /10K = 0.4mA。只要P1.1 輸出低電平GND實際小于0.3V, LED就不能導(dǎo)通,結(jié)果L
11、ED不亮。開關(guān)雙鍵的輸入:輸入先輸出高 一個按鍵 KEY_。隈在P1.6與GN比間,另一個按鍵 KEY_OF嵌P1.7與GN龍間,按 KEY_O距LED亮,按KEY OF后LED滅。同時按下LED半亮,LED保持后松開鍵的狀態(tài),即 ON OFF滅。#include <at89x52.h>#define LEDP1A1#define KEY_ONP"6#define KEY_OFFP"7void main( void )/用符號LED弋替P1_1/用符號 KEY_O玳替P1_6/用符號 KEY_OF戰(zhàn)替P1_7/單片機(jī)復(fù)位后的執(zhí)行入口,void表示空,無輸入?yún)?shù),
12、無返回值KEY_ON = 1;KEY_OFF = 1;While( 1 )/作為輸入,/作為輸入,/永遠(yuǎn)為真,首先輸出高,接下 KEY_ON P1.6則接地為0,否則輸入為1 首先輸出高,接下 KEY_OFF P1.7則接地為0,否則輸入為1 所以永遠(yuǎn)循環(huán)執(zhí)行如下括號內(nèi)所有語句(if( KEY_ON=0 )LED=1;/ 是 KEY_O概下,所示 P1.1 輸出高,LED亮if( KEY_OFF=0 )LED=0;/ 是 KEY_OF眠下,所示 P1.1 輸出低,LED滅)/松開鍵后,都不給LED賦值,所以LED保持最后按鍵狀態(tài)。/同時按下時,LED不斷亮滅,各占一半時間,交替頻率很快,由于人
13、眼慣性,看上去為半亮態(tài)數(shù)碼管的接法和驅(qū)動原理一支七段數(shù)碼管實際由8個發(fā)光二極管構(gòu)成,其中 7個組形構(gòu)成數(shù)字8的七段筆畫,所以稱為七段數(shù) 碼管,而余下的1個發(fā)光二極管作為小數(shù)點(diǎn)。作為習(xí)慣,分別給8個發(fā)光二極管標(biāo)上記號:a,b,c,d,e,f,g,h 。 對應(yīng)8的頂上一畫,按順時針方向排,中間一畫為g,小數(shù)點(diǎn)為ho我們通常又將各二極與一個字節(jié)的8 位對應(yīng),a(D0),b(D1),c(D2),d(D3),e(D4),f(D5),g(D6),h(D7),相應(yīng)8個發(fā)光二極管正好與單片機(jī)一個端口Pn的8個引腳連接,這樣單片機(jī)就可以通過引腳輸出高低電平控制8個發(fā)光二極的亮與滅,從而顯示各種數(shù)字和符號;對應(yīng)字
14、節(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個發(fā)光二極管的負(fù)極(陰極)內(nèi)接在一起,作為數(shù)碼管的一個引腳,這種數(shù)碼管則被稱為共陰數(shù)碼管,共同的引 腳則稱為共陰極,8 個正極則為段極。否 則,如果是將正極(陽極)內(nèi)接在一起 引出的,則稱為共陽 數(shù)碼管,共同的引腳 則稱為共陽極,8個 負(fù)極則為段極。以單支共陰數(shù) 碼管為例,可將段極 接到某端口 Pn,共陰 極接GND則可編寫 出對應(yīng)十六進(jìn)制碼靠示字符共陰(ft段選碼共陽橫段逃牌顯示字符技兩欖段蹄回03FHCOMC39H
15、C6H1Q6HF9HD1EHA1H25BHA4HE79H86H3垂HBOHF71H34H466H99HP73H32H56DHu3EHC1H67DH32Hr31HCEH107HF?H76EHP1H87FH30H8FFHOOH96FH煩”O(jiān)OHFFHA湖B?CH33H的七段碼表字節(jié)數(shù)據(jù)如右圖:16鍵碼顯示的程序我們在P1端口接一支共陰數(shù)碼管SLED在P2、P3端口接16個按鍵,分別編號為 KEY_Q KEY_1到KEY_F操作時只能按一個鍵,按鍵后SLED顯示對應(yīng)鍵編號。#include <at89x52.h>#define SLED P1#define KEY_0 P2A0#defi
16、ne KEY_1 P2A1#define KEY_2 P2A2#define KEY_3 P2A3#define KEY_4 P2A4#define KEY_5 P2A5#define KEY_6 P2A6#define KEY_7 P2A7#define KEY_8 P3A0#define KEY_9 P3A1#define KEY_A P3A2#define KEY_B P3A3#define KEY_C P3A4#define KEY_D P3A5#define KEY_E P3A6#define KEY_F P3A7Code unsigned char Seg7Code16= /用十六
17、進(jìn)數(shù)作為數(shù)組下標(biāo),可直接取得對應(yīng)的七段編碼字節(jié)/ 01 234 5 6 7 8 9 A b C d E F(0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71);void main( void )(unsigned char i=0;/ 作為數(shù)組下標(biāo)P2 = 0xff; /P2作為輸入,初始化輸出高P3 = 0xff; /P3作為輸入,初始化輸出高While( 1 )( if( KEY_0 = 0 ) i=0;if( KEY_1 = 0 ) i=1;if(
18、KEY_2 = 0 ) i=2;if( KEY_3 = 0 ) i=3;if( KEY_4 = 0 ) i=4;if( KEY_5 = 0 ) i=5;if( KEY_6 = 0 ) i=6;if( KEY_7 = 0 ) i=7;if( KEY_8 = 0 ) i=8;if( KEY_9 = 0 ) i=9;if( KEY_A = 0 ) i=0xA;if( KEY_B = 0 )i=0xB;if( KEY_C = 0 ) i=0xC;if( KEY_D = 0 )i=0xD;if( KEY_E = 0 ) i=0xE;if( KEY_F = 0 )i=0xF;SLED = Seg7Code
19、 i ;/開始時顯示0,根據(jù)i取應(yīng)七段編碼 第二節(jié):雙數(shù)碼管可調(diào)秒表解:只要滿足題目要求,方法越簡單越好。由于單片機(jī)I/O資源足夠,所以雙數(shù)碼管可接成靜態(tài)顯示方式,兩個共陰數(shù)碼管分別接在P1 (秒十位)和P2(秒個位)口,它們的共陰極都接地,安排兩個按鍵接在P3.2(十位數(shù)調(diào)整)和 P3.3 (個位數(shù)調(diào)整)上,為了方便計時,選用12MHz的晶體。為了達(dá)到精確計時,選用定時器方式2,每計數(shù)250重載一次,即250us,定義一整數(shù)變量計數(shù)重載次數(shù),這樣計數(shù)4000次即為一秒。定義兩個字節(jié)變量 S10和S1分別計算秒十位和秒個位。編得如下程序: #include <at89x52.h>C
20、ode unsigned char Seg7Code16= /用十六進(jìn)數(shù)作為數(shù)組下標(biāo),可直接取得對應(yīng)的七段編碼字節(jié)/ 01 234 5 6 7 89 A b C d E F(0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71; void main( void ) (unsigned int us250 = 0;unsigned char s10 = 0;unsigned char s1 = 0;unsigned char key10 = 0;/記憶按鍵狀態(tài),
21、為 1按下unsigned char key1 = 0;/記憶按鍵狀態(tài),為 1按下/初始化定時器Timer0TMOD = (TMOD & 0xF0) | 0x02;TH1 = -250;/對于8位二進(jìn)數(shù)來說,-250=6,也就是加 250次1時為256,即為0TR1 = 1;while(1)(/ 循環(huán) 1P1 = Seg7Code s10 ;/ 顯示秒十位P2 = Seg7Code s1 ;/ 顯示秒個位while( 1 )(/ 循環(huán) 2/計時處理if( TF0 = 1 )(TF0 = 0;if( +us250 >= 4000 )(us250 = 0;if( +s1 >=
22、10 )(si = 0;if( +s10 >= 6 ) s10 = 0;)break; /結(jié)束"循環(huán)2”,修改顯示)/按十位鍵處理P3.2 = 1;/P3.2 作為輸入,先要輸出高電平if( key10 = 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 )k
23、ey1=0;else (/未按鍵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個引腳控制交通燈,高電平燈亮,低電平燈滅。#include <at89x5
24、2.h>/sbit用來定義一個符號位地址,方便編程,提高可讀性,和可移植性sbit SNRed=P1A0;/南北方向紅燈sbit SNYellow =P1A1;/南北方向黃燈sbit SNGreen =P1A2;/南北方向綠燈sbit EWRed=P1A3;/東西方向紅燈sbit EWYellow =P"4;/東西方向黃燈sbit EWGreen =P1A5;/東西方向綠燈/*用軟件產(chǎn)生延時一個單位時間void Delay1Unit( void )unsigned int i, j;for( i=0; i<1000; i+ )*/for( j<0; j<100
25、0; j+ );/通過實測,調(diào)整j循環(huán)次數(shù),產(chǎn)生1ms延時/還可以通過生成匯編程序來計算指令周期數(shù),結(jié)合晶體頻率來調(diào)整j循環(huán)次數(shù),接近1ms/*延時n個單位時間*/void Delay( unsigned int n ) for( ; n!=0; n- ) Delay1Unit(); void main( void )while( 1 )SNRed=0; SNYellow=0; SNGreen=1; EWRed=1; EWYellow=0; EWGreen=0; Delay( 60 );SNRed=0; SNYellow=1; SNGreen=0; EWRed=1; EWYellow=0; E
26、WGreen=0; Delay( 10 );SNRed=1; SNYellow=0; SNGreen=0; EWRed=0; EWYellow=0; EWGreen=1; Delay( 60 );SNRed=1; SNYellow=0; SNGreen=0; EWRed=0; EWYellow=1; EWGreen=0; Delay( 10 ); 第四節(jié):數(shù)碼管驅(qū)動顯示 “ 12345678”P1端口接8聯(lián)共陰數(shù)碼管SLED8的段極:P1.7接段h, , , P1.0接段aP2端口接8聯(lián)共陰數(shù)碼管SLED8的段極:P2.7接左邊的共陰極,P2.0接右邊的共陰極方案說明:晶振頻率fosc=12M
27、Hz,數(shù)碼管采用動態(tài)刷新方式顯示,在1ms定時斷服務(wù)程序中實現(xiàn)#include <at89x92.h>unsigned char DisBuf8;全局顯示緩沖區(qū),DisBuf0對應(yīng)右 SLED DisBuf7 對應(yīng)左 SLEDvoid DisplayBrush( void ) code unsigned char cathode8=0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f;/ 陰極控制碼Code unsigned char Seg7Code16= /用十六進(jìn)數(shù)作為數(shù)組下標(biāo),可直接取得對應(yīng)的七段編碼字節(jié)0x3f,0x06,0x5b,0x4f,0x
28、66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71;static unsigned char i=0; /(0v i < 7) 循環(huán)刷新顯示,由于是靜態(tài)變量,此賦值只做一次。P2 = 0xff;/顯示消隱,以免下一段碼值顯示在前一支SLEDP1 = Seg7Code DisBufi ; /從顯示緩沖區(qū)取出原始數(shù)據(jù),查表變?yōu)槠叨未a后送出顯示P2 = cathode i ;/將對應(yīng)陰極置低,顯示if( +i >= 8 ) i=0;/指向下一個數(shù)碼管和相應(yīng)數(shù)據(jù) void Timer0IntRoute( void ) inte
29、rrupt 1 TL0 = -1000;/由于TL0只有8bits,所以將(-1000 )低8位賦給TL0TH0 = (-1000)>>8;/ 取(-1000)的高 8 位賦給 TH0,重新定時 1msDisplayBrush(); void Timer0Init( void ) TMOD=(TMOD & 0xf0) | 0x01;/初始化,定時器 T0,工作方式1TL0 = -1000 ; / 定時 1msTH0 = (-1000)>>8;TR0 = 1;/允許T0開始計數(shù)ET0 = 1;/允許T0計數(shù)溢出時產(chǎn)生中斷請求 void Display( unsig
30、ned char index, unsigned char dataValue ) DisBuf index = dataValue; void main( void ) unsigned char i;for( i=0; i<8; i+ ) Display(i, 8-i); /DisBuf0為右,DisBuf7 為左Timer0Init();EA = 1 ;/允許CPU響應(yīng)中斷請求While(1); 第五節(jié):鍵盤驅(qū)動指提供一些函數(shù)給任務(wù)調(diào)用,獲取按鍵信息,或讀取按鍵值。 定義一個頭文檔<KEY.H>,描述可用函數(shù),如下:#ifndef _KEY_H_/防止重復(fù)引用該文檔,如
31、果沒有定義過符號_KEY_H_,則編譯下面語句#define _KEY_H_/ 只要引用過一次,即 #include <key.h> ,則定義符號 _KEY_H_unsigned char keyHit( void );/如果按鍵,則返回非0,否則返回0unsigned char keyGet( void );/讀取按鍵值,如果沒有按鍵則等待到按鍵為止void keyPut( unsigned char ucKeyVal );/ 保存按鍵值 ucKeyVal 到按鍵緩沖隊列末void keyBack( unsigned char ucKeyVal );/ 退回鍵值 ucKeyVal
32、 到按鍵緩沖隊列首#endif定義函數(shù)體文檔KEY.C ,如下:# include " key.h ”#define KeyBufSize 16 /定義按鍵緩沖隊列字節(jié)數(shù)unsigned char KeyBuf KeyBufSize ;/定義一個無符號字符數(shù)組作為按鍵緩沖隊列。該隊列為先進(jìn)/先出,循環(huán)存取,下標(biāo)從0到 KeyBufSize-1unsigned char KeyBufWp=0; /作為數(shù)組下標(biāo)變量,記錄存入位置unsigned char KeyBufRp=0; /作為數(shù)組下標(biāo)變量,記錄讀出位置/如果存入位置與讀出位置相同,則表明隊列中無按鍵數(shù)據(jù)unsigned char
33、 keyHit( void ) if( KeyBufWp = KeyBufRp ) return( 0 ); else return( 1 ); unsigned char keyGet( void ) unsigned char retVal; / 暫存讀出鍵值while( keyHit()=0 );等待按鍵,因為函數(shù)keyHit()的返回值為0表示無按鍵retVal = KeyBuf KeyBufRp ;/ 從數(shù)組中讀出鍵值if( +KeyBufRp >= KeyBufSize ) KeyBufRp=0;/讀位置加1 ,超出隊列則循環(huán)回初始位置return( retVal ); vo
34、id keyPut( unsigned char ucKeyVal ) KeyBuf KeyBufWp = ucKeyVal; / 鍵值存入數(shù)組if( +KeyBufWp >= KeyBufSize ) KeyBufWp=0;/存入位置加1 ,超出隊列則循環(huán)回初始位置 /*由于某種原因,讀出的按鍵,沒有用,但其它任務(wù)要用該按鍵,但傳送又不方便。此時可以退回按鍵隊列。 就如取錯了信件,有必要退回一樣*/void keyBack( unsigned char ucKeyVal )/*如果KeyBufRp=0;減1后則為FFH,大于KeyBufSize,即從數(shù)組頭退回到數(shù)組尾?;蛘哂捎诟蓴_使得
35、KeyBufRp超出隊列位置,也要調(diào)整回到正常位置,*/if( -KeyBufRp >= KeyBufSize ) KeyBufRp=KeyBufSize-1;KeyBuf KeyBufRp = ucKeyVal; / 回存鍵值下面漸進(jìn)講解鍵盤物理層的驅(qū)動。電路共同點(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=/ 0123456789 A b C d EF0x3f,0x06, 0x5b
36、,0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f,0x6f,0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71;例一:P1.0接一按鍵到GND鍵編號為6',顯示按鍵#include <at89x52.h>#include“KEY.H' void main( void )(P1_0 = 1;/作為輸入引腳,必須先輸出高電平while( 1 )/永遠(yuǎn)為真,即死循環(huán)( if( P1_0 = 0 )/如果按鍵,則為低電平( keyPut( 6 );/保存按鍵編號值為按鍵隊列while( P1_0 = 0 );/如果一直按著鍵,則不停地
37、執(zhí)行該循環(huán),實際是等待松鍵)if( keyHit() != 0 )/如果隊列中有按鍵P2=Seg7Code keyGet() ;/從隊列中取出按鍵值,并顯示在數(shù)碼管上) )例二:在例一中考慮按鍵20m s抖動問題。#include <at89x52.h>#include“KEY.H'void main( void )(P1_0 = 1;/作為輸入引腳,必須先輸出高電平while( 1 )/永遠(yuǎn)為真,即死循環(huán)( if( P1_0 = 0 )/如果按鍵,則為低電平 delay20ms(); /延時20ms跳過接下抖動keyPut( 6 );/保存按鍵編號值為按鍵隊列while(
38、 P1_0 = 0 );/如果一直按著鍵,則不停地執(zhí)行該循環(huán),實際是等待松鍵delay20ms(); /延時20ms跳過松開抖動 ) if( keyHit() != 0 )/如果隊列中有按鍵P2=Seg7Code keyGet() ;/從隊列中取出按鍵值,并顯示在數(shù)碼管上) )例三:在例二中考慮干擾問題。即小于20ms的負(fù)脈沖干擾。#include <at89x52.h>#include“KEY.H'void main( void )(P1_0 = 1;/作為輸入引腳,必須先輸出高電平while( 1 )/永遠(yuǎn)為真,即死循環(huán)( if( P1_0 = 0 )/如果按鍵,則為低
39、電平( delay20ms(); /延時20ms,跳過接下抖動if( P1 0 = 1 ) continue; / 假按鍵keyPut( 6 );/保存按鍵編號值為按鍵隊列while( P1_0 = 0 );/如果一直按著鍵,則不停地執(zhí)行該循環(huán),實際是等待松鍵delay20ms();/延時20ms,跳過松開抖動) if( keyHit() != 0 )/如果隊列中有按鍵P2=Seg7Code keyGet() ;/從隊列中取出按鍵值,并顯示在數(shù)碼管上) )例四:狀態(tài)圖編程法。通過 20ms周期中斷,掃描按鍵。/*采用晶體為12KHz時,指令周期為1ms (即主頻為1KHz),這樣T0工作在定時
40、器方式2, 8位自動重載。 計數(shù)值為20,即可產(chǎn)生20ms的周期性中斷,在中斷服務(wù)程序中實現(xiàn)按鍵掃描*/ #include <at89x52.h>#include“KEY.H'void main( void )TMOD = (TMOD & 0xf0 ) | 0x02;/TH0 = -20;/TL0=TH0;/不改變T1的工作方式,T0為定時器方式2 計數(shù)周期為20個主頻脈,即20ms先軟加載一次計數(shù)值TR0=1;/允許T0開始計數(shù)ET0=1;/允許T0計數(shù)溢出時產(chǎn)生中斷請求EA=1;/允許CPUP向應(yīng)中斷請求while( 1 ) (永遠(yuǎn)為真,即死循環(huán)if( keyH
41、it() != 0 )/如果隊列中有按鍵P2=Seg7Code keyGet();/從隊列中取出按鍵值,并顯示在數(shù)碼管上void timer0int( void ) interrupt 1/20ms ; T0的中斷號為1( static unsigned char sts=0;P1_0 = 1;作為輸入引腳,必須先輸出高電平switch( sts )/按鍵則轉(zhuǎn)入狀態(tài)1(case 0: if( P1_0=0 ) sts=1; break;case 1:if( P1_0=1 ) sts=0;/else( sts=2; keyPut( 6 ); /假按錯,或干擾,回狀態(tài) 0確實按鍵,鍵值入隊列,并轉(zhuǎn)
42、狀態(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)else sts=0;/真松鍵,回狀態(tài)0,等待下一次按鍵過程例五:狀態(tài)圖編程法。/*如果采用晶體為12MHz時,指令周期為1us(即主頻為1MHZ,要產(chǎn)生20ms左右的計時,則計數(shù)值達(dá)到20000,T0工作必須為定時器方式 1, 16位非自動重載,即可產(chǎn)生 20ms的周期性中斷,在中斷服務(wù)程序中實現(xiàn)按鍵掃描*/ #include <at89x52.h>#include“KEY.H'void main
43、( void )TMOD = (TMOD & 0xf0 ) | 0x01;/不改變T1的工作方式,T0為定時器方式1TL0 = -20000;/TH0 = (-20000)>>8;/TR0=1;/計數(shù)周期為20000個主頻脈,自動取低 8位右移8位,實際上是取高8位允許T0開始計數(shù)ET0=1;/允許T0計數(shù)溢出時產(chǎn)生中斷請求EA=1;/允許CPUP向應(yīng)中斷請求while( 1 )/永遠(yuǎn)為真,即死循環(huán)if( keyHit() != 0 )/如果隊列中有按鍵P2=Seg7Code keyGet();/從隊列中取出按鍵值,并顯示在數(shù)碼管上void timer0int( void
44、) interrupt 1 ( static unsigned char sts=0;/20ms ; T0的中斷號為1TL0 = -20000;/方式1為軟件重載TH0 = (-20000)>>8;P1_0 = 1;/右移8位,實際上是取局/作為輸入引腳,必須先輸出高電平switch( sts )case 0: if( P1_0=0 ) sts=1; break;/按鍵則轉(zhuǎn)入狀態(tài)case 1:if( P1_0=1 ) sts=0;/else( sts=2; keyPut( 6 ); / break;假按錯,或干擾,回狀態(tài) 0確實按鍵,鍵值入隊列,并轉(zhuǎn)狀態(tài) 2case 2: if(
45、P1_0=1 ) sts=3; break;/如果松鍵,則轉(zhuǎn)狀態(tài)3case 3:if( P1_0=0 ) sts=2;/else sts=0;/假松鍵,回狀態(tài)真松鍵,回狀態(tài)0,等待下一次按鍵過程例六:4X4按鍵。/*由P1端口的高4位和低4位構(gòu)成4X4的矩陣鍵盤,本程序只認(rèn)為單鍵操作為合法,同時按多鍵時無效。這樣下面的X, 丫的合法值為0x7, 0xb, 0xd, 0xe, 0xf,通過表keyCode影射變換可得按鍵值*#include <at89x52.h>#incudeaKEY.H,unsigned char keyScan( void )/返回0表示無按鍵,或無效按鍵,其它
46、值為按鍵編碼值 code unsigned char keyCode16=/0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 3, 4, 0 );unsigned char x, y, retVal;P1=0x0f;/低四位輸入,高四位輸出 0x=P1&0x0f;/P1輸入后,清高四位,作為X值P1=0xf0;/高四位輸入,低四位輸出 0y=(P1 >> 4)& 0x0f;/P1輸入
47、后移位到低四位,并清高四位,作為 丫值retVal = keyCodex*4 + keyCodey;/根據(jù)本公式倒算按鍵編碼if( retVal=0 ) return(0); else return( retVal-4 );)/比如按鍵1 ',得X=0x7, Y=0x7,算得retVal= 5 ,所以返回函數(shù)值 1。/雙如按鍵7',得X=0xb, Y=0xd,算得retVal=11 ,所以返回函數(shù)值 7。void main( void )TMOD = (TMOD & 0xf0) | 0x01;/不改變T1的工作方式,T0為定時器方式1TL0 = -20000;/計數(shù)周期
48、為20000個主頻脈,自動取低 8位TH0 = (-20000)>>8;/右移8位,實際上是取高8位TR0=1;/允許T0開始計數(shù)ET0=1;/允許T0計數(shù)溢出時產(chǎn)生中斷請求EA=1;/允許CPLP向應(yīng)中斷請求while( 1 )/永遠(yuǎn)為真,即死循環(huán)if( keyHit() != 0 )/如果隊列中有按鍵P2=Seg7Code keyGet();/從隊列中取出按鍵值,并顯示在數(shù)碼管上void timer0int( void ) interrupt 1/20ms ; T0的中斷號為1/方式1為軟件重載/右移8位,實際上是取局 static unsigned char sts=0;TH
49、0 = (-20000)>>8;8位/按鍵則轉(zhuǎn)入狀態(tài)1/假按錯,或干擾,回狀態(tài) 0/確實按鍵,鍵值入隊列,并轉(zhuǎn)狀態(tài)2/如果松鍵,則轉(zhuǎn)狀態(tài) 3/假松鍵,回狀態(tài)2/真松鍵,回狀態(tài)0,等待下一次按鍵過程TL0 = -20000;P1_0 = 1;/作為輸入引腳,必須先輸出高電平switch( sts )case 0: if( keyScan()!=0 ) sts=1; break;case 1:if( keyScan()=0 ) sts=0;else sts=2; keyPut( keyScan() ); ) break;case 2: if(keyScan()=0 ) sts=3; b
50、reak;case 3:if( keyScan()!=0 ) sts=2;else sts=0;第六節(jié):低頻頻率計實例目的:學(xué)時定時器、計數(shù)器、中斷應(yīng)用 說明:選用24MHz的晶體,主頻可達(dá) 2MHz用T1產(chǎn)生100us的時標(biāo),T0作信號脈沖計數(shù)器。假設(shè)晶體頻 率沒有誤差,而且穩(wěn)定不變(實際上可達(dá)萬分之一);被測信號是周期性矩形波(正負(fù)脈沖寬度都不能小于0.5us ),頻率小于1MHz大于1Hz。要求測量時標(biāo)1S,測量精度為0.1%。解:從測量精度要求來看,當(dāng)頻率超過 1KHz時,可采用1S時標(biāo)內(nèi)計數(shù)信號脈沖個數(shù)來測量信號頻,而信 號頻率低于1KHz時,可以通過測量信號的周期來求出信號頻率。兩
51、種方法自動轉(zhuǎn)換。對于低于1KHz的信號,信號周期最小為1m§也就是說超過1000us ,而我們用的定時器計時脈沖周期 為0.5us ,如果定時多計或少計一個脈沖,誤差為1us,所以相對誤差為1us/1000us=0.1%。信號周期越大,即信號頻率越低,相對誤差就越小。從上面描述來看,當(dāng)信號頻率超過1KHz后,信號周期就少于1000us,顯然采用上面的測量方法,不能達(dá)到測量精度要求,這時我們采用1S單位時間計數(shù)信號的脈沖個數(shù),最少能計到1000個脈沖,由于信號頻率不超過1MHz而我們定時脈沖為 2MHz最差多計或少計一個信號脈沖,這樣相對誤差為1/1000,可見信號頻率越高,相對誤差越
52、小。信號除輸入到T1 (P3.5 )夕卜,還輸入到INT1 (P3.3 )。unsigned int us100;/對100us時間間隔單位計數(shù),即有多少個100us。unsigned char Second;unsigned int K64;/對64K單位計數(shù),即有多少個 64Kunsigned char oldT0;unsigned int oldus, oldK64, oldT1;unsigned long fcy;/存放頻率值,單位為 Hzbit HighLow=1;void InitialHigh( void ) (/1 :表示信號超過1KH乙0:表示信號低于1KHz。IE=0; IP=0; HighLo
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 防治老鼠服務(wù)合同協(xié)議書
- 建筑樁基工程施工合同
- 電熱水器維修合同
- 法律行業(yè)智能訴訟輔助工具研發(fā)方案
- 地暖承包合同
- 教育行業(yè)管理與教學(xué)實踐指南
- 農(nóng)業(yè)環(huán)境保護(hù)與管理指導(dǎo)書
- DeepSeek簡單版使用指南
- 店面承包合作協(xié)議合同
- 集裝箱活動房租賃合同樣本
- XX學(xué)校服采購工作方案(含一封信、備案表、反饋表)
- GB/T 33107-2016工業(yè)用碳酸二甲酯
- GB/T 18938-2008家用和類似用途的面包片電烘烤器性能測試方法
- 簡約卡通小學(xué)生校園文明禮儀教育PPT模板
- 勞動合同法經(jīng)典講義
- 三位數(shù)乘一位數(shù)練習(xí)題(精選100道)
- 教學(xué)第二章-毫針刺法1課件
- 產(chǎn)業(yè)園區(qū)環(huán)保管家實踐和案例
- 醫(yī)學(xué)約束帶的使用課件
- 傳染病防控工作職能部門間協(xié)調(diào)機(jī)制及流程
- 社會團(tuán)體法定代表人登記表
評論
0/150
提交評論