單片機(jī)C語言編程_第1頁
單片機(jī)C語言編程_第2頁
單片機(jī)C語言編程_第3頁
單片機(jī)C語言編程_第4頁
單片機(jī)C語言編程_第5頁
已閱讀5頁,還剩56頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、單片機(jī)C語言編程主講教師:廉哲QQ:17434548電話公室:綜合樓C31851單片機(jī)硬件結(jié)構(gòu)C51基礎(chǔ)知識(shí)及其基本程序設(shè)計(jì)C51函數(shù)、數(shù)組、指針定義及應(yīng)用單片機(jī)內(nèi)部資源及其C語言編程單片機(jī)資源擴(kuò)展及其C語言編程綜合程序設(shè)計(jì)考試課程主要內(nèi)容: 四 C51編程設(shè)計(jì)4.1 MCS-51內(nèi)部資源使用的C語言編程4.2 MCS-51片外擴(kuò)展的C語言編程4.3 頻率量測量的C語言編程4.1 MCS-51內(nèi)部資源使用的C語言編程4.1.1 中斷應(yīng)用的C語言編程 C51編譯器支持在C源程序中直接開發(fā)中斷程序。中斷服務(wù)程序是通過按規(guī)定語法格式定義的一個(gè)函數(shù)。 中斷服務(wù)程序的函數(shù)定義的

2、語法格式如下: 返回值 函數(shù)名(參數(shù)) interrupt musing n using n 選項(xiàng)用于實(shí)現(xiàn)工作寄存器組的切換,n是中斷服務(wù)子程序中選用的工作寄存器組號(hào)(0 3)。在許多情況下,響應(yīng)中斷時(shí)需保護(hù)有關(guān)現(xiàn)場信息,以便中斷返回后,能使中斷前的源程序從斷點(diǎn)處繼續(xù)正確地執(zhí)行下去。這在MCS-51單片機(jī)中,能很方便地利用工作寄存器組的切換來實(shí)現(xiàn)。即在進(jìn)入中斷服務(wù)程序前的程序中使用一組工作寄存器,進(jìn)入中斷服務(wù)程序后,由using n切換到另一組寄存器,中斷返回后又恢復(fù)到原寄存器組。這樣互相切換的兩組寄存器中的內(nèi)容彼此都沒有被破壞。圖 4.1 擴(kuò)展多個(gè)中斷源 例1 圖7.5所示是利用優(yōu)先權(quán)解碼芯

3、片,在單片機(jī)8031的一個(gè)外部中斷INT1上擴(kuò)展多個(gè)中斷源的原理電路圖。圖中是以開關(guān)閉合來模擬中斷請求信號(hào)。當(dāng)有任一中斷源產(chǎn)生中斷請求,能給8031的INT1引腳送一個(gè)有效中斷信號(hào),由P1的低3位可得對(duì)應(yīng)中斷源的中斷號(hào)。for(; ;) if(flag) /* 有中斷 */ switch(status) /* 根據(jù)中斷源分支 */ case 0 : break ; /* 處理IN0 */ case 1 : break ; /* 處理IN1 */ case 2 : break; /* 處理IN2 */ case 3 : break; /* 處理IN3 */ default : ; flag=0

4、; /* 處理完成清標(biāo)志 */ 4.1.2 定時(shí)器/計(jì)數(shù)器(T/C)應(yīng)用的C語言編程 例2 設(shè)單片機(jī)的fosc=12 MHz晶振,要求在P1.0腳上輸出周期為2 ms的方波。 周期為2 ms的方波要求定時(shí)時(shí)間隔1 ms,每次時(shí)間到P1.0取反。 機(jī)器周期=12/fosc=1 s 需計(jì)數(shù)次數(shù)=1000/(12/fosc)=1000/1=1000 由于計(jì)數(shù)器是加1計(jì)數(shù),為得到1000個(gè)計(jì)數(shù)之后的定時(shí)器溢出,必須給定時(shí)器置初值為-1000(即1000的補(bǔ)數(shù))。(1) 用定時(shí)器0的方式1編程,采用查詢方式,程序如下: # include sbit P1_0=P10 ; void main(void)

5、TMOD=0 x01 ; /* 設(shè)置定時(shí)器1為非門控制方式1*/ TR0=1 ; /* 啟動(dòng) T/C0 */ for( ; ;) TH0= -(1000/256) ; /* 裝載計(jì)數(shù)器初值 */ TL0= -(1000%256) ; do while (!TF0) ; /* 查詢等待TF0置位 */ P1_0=!P1_0; /* 定時(shí)時(shí)間到P1.0反相 */ TF0=0; /* 軟件清 TF0 */ (2) 用定時(shí)器0的方式1編程,采用中斷方式。程序如下: # include sbit P1_0=P10 ; void time (void) interrupt 1 using 1 /* T/C

6、0中斷服務(wù)程序入口 */ P1_0=!P1_0 ; /* P1.0取反 */ TH0= -(1000/256); / * 重新裝載計(jì)數(shù)初值 */ void main( void ) TMOD=0 x01 ; /* T/C0工作在定時(shí)器非門控制方式1 */ P1_0=0; TH0= -(1000/256 ); /* 預(yù)置計(jì)數(shù)初值 */ TL0= -(1000%256) ; EA=1 ; /* CPU中斷開放 */ ET0= 1 ; /* T/C0中斷開放 */ TR0=1 ; /* 啟動(dòng)T/C0開始定時(shí) */ do while(1) ; /* 等待中斷 */ 例3 采用10 MHz晶振,在P1.

7、0腳上輸出周期為2.5 s,占空比20%的脈沖信號(hào)。 10 MHz晶振,使用定時(shí)器最大定時(shí)幾十毫秒。取10 ms定時(shí),周期2.5 s需250次中斷,占空比20%,高電平應(yīng)為50次中斷。 10 ms定時(shí),晶振fosc=10 MHz。 需定時(shí)器計(jì)數(shù)次數(shù)=1010310/12=8333# include # define uchar unsigned charuchar period=250;uchar high=50;timer0( )interrupt 1 using 1 /* T/C0中斷服務(wù)程序 */TH0= - 8333/256 ; /* 重置計(jì)數(shù)值 */TL0= - 8333%256 ;

8、 if(+time=high)P1=0; /* 高電平時(shí)間到變低 */else if (time=period) /* 周期時(shí)間到變高 */time=0 ;P1=1 ; 圖2.2 中斷服務(wù)程序流程圖 產(chǎn)生一個(gè)占空比變化脈沖信號(hào)的程序,它產(chǎn)生的脈寬調(diào)制信號(hào)用于電機(jī)變速控制。# include # define uchar unsigned char # define uint unsigned int unchar time,status,percent,period;bit one_round;uint oldcount,target=500;void pulse (void) interru

9、pt 1 using 1 /* T/C0中斷服務(wù)程序 */ TH0= - 833/256 ; /* 1ms - -10 MHz */ newcount ; newcount. byte. hi=TH1; newcount .byte .lo=TL1 ; period=newcount .word - oldcount ; /* 測得周期 */ oldcount=newcount .word ; one_round=1; /* 每轉(zhuǎn)一圈,引起中斷,設(shè)置標(biāo)志 */ void main ( void ) IP=0 x04 ; /* 置INT1為高位優(yōu)先級(jí) */ TMOD= 0 x11 ; /* T0

10、,T1 16位方式 */ TCON=0 x54 ; /* T0,T1運(yùn)行,IT1邊沿觸發(fā) */ TH1=0;TL1=0; /* 設(shè)置初始計(jì)數(shù)值 */ IE=0 x86 ; /* 允許中斷EX1,ET0 */ for (; ;) if (one_round ) /* 每轉(zhuǎn)一圈,調(diào)整 */ if ( period target ) if (percent 0 ) - -percent ; / * 占空比減 */ one_round=0 ; 4.1.3 串行口使用的C語言編程 例4 單片機(jī)fosc=11.0592 MHz,波特率為9600,各設(shè)置32字節(jié)的隊(duì)列緩沖區(qū)用于發(fā)送接收。設(shè)計(jì)單片機(jī)和終端或另

11、一計(jì)算機(jī)通信的程序。 單片機(jī)串行口初始化成9600波特,中斷程序雙向處理字符,程序雙向緩沖字符。背景程序可以放入和提取在緩沖區(qū)的字符串,而實(shí)際傳入和傳出SBUF的動(dòng)作由中斷完成。 Loadmsg 函數(shù)加載緩沖數(shù)組,標(biāo)志發(fā)送開始。緩沖區(qū)分發(fā)(t)和收(r)緩沖,緩沖區(qū)通過兩種指示(進(jìn)in和出out)和一些標(biāo)志(滿full,空empty,完成done)管理。隊(duì)列緩沖區(qū)32字節(jié)接收緩沖(r_buf)區(qū)滿,不能再有字符插入。當(dāng)t_in=t_out,發(fā)送緩沖區(qū)(t_buf)空,發(fā)送中斷清除,停止UART請求。具體程序如下:# include # define uchar unsigned char uc

12、har xdata r_buf32 ; /* item1 */uchar xdata t_buf32 ;uchar r_in , r_out , t_in , t_done ; /* 隊(duì)列指針 */bit r_full , t_empty , t_done ; /* item2 */code uchar m = this is a test program rn ;serial ( ) interrupt 4 using 1 /* item3 */ if( RI & r_full ) r_bufr_in=SBUF ; RI=0 ; r_in= +r_in & ox1f ; if ( r_in=

13、 =r_out ) r_full=1; else if (TI & t_empty ) SBUF=t_buf t_out ; TI=0; t_out = + t_out & 0 x1f ; i f ( t_out= =t_in ) t_empty=1 ; else if (TI ) TI=0; t_done=1 ; void loadmsg (uchar code * msg ) /* item4 */ while (*msg !=0 )& ( t_in+1)t_out ) & 0 x1f ) !=0 ) / *測試緩沖區(qū)滿 */ t_ buf t_in= * msg ; msg+ ; t_i

14、n = + t_in & 0 x1f ; if ( t_done ) TI = 1 ; t_empty =t_done =0 ; /* 完成重新開始 */ main ( ) /* item7 */ TMOD=0 x20 ; /* 定時(shí)器1方式2 */ TH1=0 xfd ; /* 9600波特11.0592 MHz */ TCON=0 x40 ; /* 啟動(dòng)定時(shí)器1 */ SCON=0 x50 ; /* 允許接收 */ IE=0 x90 ; /* 允許串行口中斷 */ t_empty=t_done=1 ; r_full =0 ; r_out=t_in =0 ; r_ in=1 ; /* 接收緩

15、沖和發(fā)送緩沖置空 */ for ( ; ; ) loadmsg ( & m ) ; processmsg ( ); item1 :背景程序放入和提取字符隊(duì)列緩沖區(qū)。 item2 :緩沖區(qū)狀態(tài)標(biāo)志。 item3 :串行口中斷服務(wù)程序,從RI,TI判別接收或發(fā)送中斷,由軟件清除。判別緩沖區(qū)狀態(tài)(滿full,空empty)和全部發(fā)送完成(done)。 item4 :此函數(shù)把字符串放入發(fā)送緩沖區(qū),準(zhǔn)備發(fā)送。 item5 :接受字符的處理程序,實(shí)際應(yīng)用自定義。 item6 :此函數(shù)逐一處理接收緩沖區(qū)的字符。 item7 :主程序即背景程序,進(jìn)行串行口的初始化,載入字符串,處理接收的字符串。圖4.3 80

16、31擴(kuò)展8255與打印機(jī)接口的電路 向打印機(jī)輸出字符串WELCOME的程序如下:# include # include # define uchar unsigned char # define COM8255 XBYTE0 x007f /* 命令口地址 */# define PA8255 XBYTE 0 x007c /* 口A地址 */# define PC8255 XBYTE 0 x007e /* 口C 地址 */void toprn ( uchar *p ) / * 打印字符串函數(shù) */ while ( * p!= 0) while ( 0 x80 & PC8255 )! =0 ) ;

17、/* 查詢等待打印機(jī)的BUSY狀態(tài)*/ PA8255 = * p ; /* 輸出字符 */ COM8255 = 0 x00 ; /* 模擬STB脈沖 */ COM8255=0 x01 ; p+ ; void main ( void ) uchar idata prn = WELCOME; /* 設(shè)測試用字符串 */ COM8255=0 x8e ; /* 輸出方式選擇命令 */ toprn ( prn ) ; /* 打印字符串 */ 例6 EPROM編程器。 由8031擴(kuò)展1片EPROM2716、2片SRAM6116及1片8255構(gòu)成EPROM編程器,編程對(duì)象是EPROM2732。擴(kuò)展編程系統(tǒng)中

18、2716用來存放固化用監(jiān)控程序,用戶的待固化程序放在2片6116中。8255的口A作編程器數(shù)據(jù)口,口B輸出2732的低8位地址,PC3PC0輸出2732高4位地址,PC7作2732啟動(dòng)保持控制器與PGM連接。 譯碼地址為:6116(1):0800H;6116(2):1000H17FFH;8255的口A:07FCH;口B:07FDH;口C:07FEH;命令口:07FFH。 8255的口A、口B、口C均工作在方式0輸出,方式選擇命令字為80H;2732的啟動(dòng)編程和停止編程,由PC7的復(fù)位/置位控制,當(dāng)PC7=0時(shí)啟動(dòng)編程,PC7=1時(shí),編程無效。 EPROM編程如下所示,參數(shù)為RAM起始地址、EP

19、ROM起始地址和編程字節(jié)數(shù)。# include # include # define COM8255 XBYTE 0 x07ff # define PA8255 XBYTE 0 x07fc# define PB8255 XBYTE 0 x07fd # define PC8255 XBYTE 0 x07fe # define uchar unsigned char # define uint unsigned int void d1_ms ( unit x ) ;void program (ram , eprom , con )uchar xdata * ram ; /* RAM起始地址 */u

20、int eprom , con ; /* EPROM起始固化地址,固化長度 */ int i ; COM8255=0 x08 ; /* 送方式選擇命令字 */ COM8255=0 x0f ; /* PC7=1 */ for (i=0 ; icon ;i+ ) PA8255= * ram ; /* 固化內(nèi)容口A鎖存 */ PB8255=eprom % 256 ; /* 2732地址低8位 */ PC8255=eprom /256 ; /* 2732地址高4位 */ eprom + ; ram + ; COM8255=0 x0e ; /* PC7=0 */ d1_ms (50 ) ; COM825

21、5=0 x0f ; /* PC7=1 */ main ( ) program ( 0 x1000,0 x0000,0 x0100 ) ; 4.2.2 MCS-51數(shù)據(jù)采集的C語言編程例7 ADC0809與8031接口的數(shù)據(jù)采集程序舉例。圖2.4 ADC0809與8031的接口電路程序如下: # include # include # define uchar unsigned char # define IN0 XBYTE 0 x7ff8 /* 設(shè)置AD0809的通道0地址 */ sbit ad_busy =P33 ; /* 即EOC狀態(tài) */ void ad0809 ( uchar idat

22、a *x ) /* 采樣結(jié)果放指針中的A/D采集函數(shù) */ uchar i ; uchar xdata *ad_adr ; ad_adr= & IN0 ; for ( i=0 ; i8 ;i+ ) /* 處理8通道 */ *ad_adr=0 ; /* 啟動(dòng)轉(zhuǎn)換 */ i=i ; /* 延時(shí)等待EOC變低 */ i=i ; while (ad_busy = =0 ) ; /* 查詢等待轉(zhuǎn)換結(jié)束 */ xi = * ad_adr ; /* 存轉(zhuǎn)換結(jié)果 */ ad_adr + ; /* 下一通道 */ void main ( void ) static uchar idata ad 10 ; ad0

23、809 ( ad ) ; /* 采樣AD0809通道的值 */ 例8 AD574與8031接口的數(shù)據(jù)采集程序舉例。圖2.5 AD574與8031的接口電路源程序如下:# include # inlucde # define uint unsigned int # define ADCOM XBYTE 0 xff7c /* 使A0=0 ,R/C=0, CS=0 */# define ADLO XBYTE 0 xff7f /* 使 R/C =1,A0=1, CS=0 */# define ADHI XBYTE 0 xff7d /* 使R/C=1,A0=0,CS =0 */sbit r = P3 7

24、 ;sbit w = P3 6 ;sbit adbusy = P1 0 ;uint ad574 ( void ) /* AD574轉(zhuǎn)換器 */ r = 0 ; /* 產(chǎn)生CE=1 */ w = 0 ; ADCOM = 0 ; /* 啟動(dòng)轉(zhuǎn)換 */ while ( adbusy = =1 ) ; /* 等待轉(zhuǎn)換*/ return ( ( uint )(ADHI4 )+( ADLO &0 x0f ) ); /* 返回12位采樣值*/ main ( ) uint idata result ; result =ad574 ( ) ; /* 啟動(dòng)AD574進(jìn)行一次轉(zhuǎn)換,得轉(zhuǎn)換結(jié)果 */ 2.2.3 MC

25、S-51輸出控制的C語言編程例9 8031與DAC0832雙緩沖接口的數(shù)據(jù)轉(zhuǎn)換程序舉例。圖4.6 DAC 0832的雙緩沖接口電路將data1和data2數(shù)據(jù)同時(shí)轉(zhuǎn)換為模擬量的C51程序如下:# include # include # define INPUTR1 XBYTE 0 x8fff # define INPUTR2 XBYTE 0 xa7ff# define DACR XBYTE 0 x2fff # define uchar unsigned char void dac2b (data1 ,data2 )uchar data1 , data2 ; INPUTR1 = data1 ;

26、/* 送數(shù)據(jù)到一片0832 */ INPUTR2 = data2 ; /* 送數(shù)據(jù)到另一片0832 */ DACR= 0 ; /* 啟動(dòng)兩路D/A 同時(shí)轉(zhuǎn)換 * /例10 8031與DAC0832單緩沖區(qū)接口的數(shù)據(jù)轉(zhuǎn)換舉例。圖4.7 DAC0832與8031 的單緩沖接口 按片選線確定FFFEH為DAC0832的端口地址。使運(yùn)行輸出端輸出一個(gè)鋸齒波電壓信號(hào)的C51程序如下:# include # include # define DA0832 XBYTE 0 xfffe # define uchar unsigned char # define uint unsigned int void s

27、tair (void ) uchar i ; while ( 1 ) for ( i=0 ; i=255 ; i=I+ ) /* 形成鋸齒波輸出值,最大值為255 */ DA0832 = i ; /* D/A轉(zhuǎn)換輸出 */ 例11 8031與AD7521接口的數(shù)據(jù)轉(zhuǎn)換程序舉例。圖4.8 AD7521與8031的接口 使AD7521輸出梯形波的C51程序如下:# include # include # define DA7521L XBYTE0 x7fff # define DA7521H XBYTE0 xbfff # define UP 0 x010# define T 1000# defin

28、e uint unsigned int void dlms ( uint a );void stair(void) uint i ; for ( i=0 ; i=4095 ; i=i+UP ) /* 以階高增量增值,形成梯形波輸出值,最大4095*/ DA7521L= i % 256 ; /* 送低8位數(shù)據(jù)到第一級(jí)緩沖器 */ DA7521H= i /256 ; /* 送高4位數(shù)據(jù)到高4位緩沖器,同時(shí)送低8位到第二級(jí) /* 緩沖轉(zhuǎn)換 */ dlms ( T ) ; /* 延時(shí) */ 4.3 頻率量測量的C語言編程4.3.1 測量頻率法 測量頻率法的最簡單的接口電路,可將頻率脈沖直接連接到MCS

29、-51的T1端,將8031的T/C0用作定時(shí)器,T/C1用作計(jì)數(shù)器。在T/C0定時(shí)時(shí)間里,對(duì)頻率脈沖進(jìn)行計(jì)數(shù)。T/C1的計(jì)數(shù)值便是單位定時(shí)時(shí)間里的脈沖個(gè)數(shù)。定時(shí)輸入脈沖 T圖2.10測量頻率中的脈沖丟失例12 帶同步控制的頻率測量。圖4.11 帶同步控制的頻率測量法接口 控制時(shí),首先P1.0發(fā)一個(gè)清零負(fù)脈沖,使U1、U2兩個(gè)D觸發(fā)器復(fù)位,其輸出封鎖與門G1和G2。接著由P1.1發(fā)一個(gè)啟動(dòng)正脈沖,其有效上升沿使U1=1,門G1被開放。之后,被測脈沖上升沿通過G2送T1計(jì)數(shù);同時(shí)U2輸出的高電平使INT0 =1,定時(shí)器0的門控GATE有效,啟動(dòng)T/C0開始定時(shí)。直到定時(shí)結(jié)束時(shí),從P1.0發(fā)一負(fù)脈沖

30、,清零 U2,封鎖G2,停止T/C1計(jì)數(shù),完成一次頻率采樣過程。 測量T/C定時(shí)時(shí)間為500 ms,這樣長的時(shí)間定時(shí),先由T/C0定時(shí)100 ms,之后軟件5次中斷后的時(shí)間即為5100 ms=500 ms。中斷次數(shù)的計(jì)數(shù)值在msn中。 T/C0定時(shí)100 ms的計(jì)數(shù)初值:03B0H。計(jì)數(shù)器1采用16位計(jì)數(shù)。設(shè)T/C0為高優(yōu)先級(jí),允許計(jì)數(shù)中斷過程定時(shí)中斷,即定時(shí)時(shí)間到就中止計(jì)數(shù)。tf為500 ms定時(shí)時(shí)間到標(biāo)志。程序如下:#include #define uchar unsigned char#define uint unsigned int#define A 5 /*500 ms 的中斷次數(shù)*/sbit P1_0=P10;sbit P1_1=P11;uchar msn=A;bit idata tf=0; /*500 ms時(shí)間到標(biāo)志*/uint count(void) P1_0=0 ; P1_0=1; /*產(chǎn)生清零用負(fù)脈沖*/ TMOD=0 x59 ; TH1=0 x00; TL1=0 x00;/* T/C1計(jì)數(shù)器 */ TH0=0 x3c ;TL0=0 xb0; /* T/C0定時(shí)器100 m

溫馨提示

  • 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)論