單片機(jī)原理及應(yīng)用李建忠_第1頁
單片機(jī)原理及應(yīng)用李建忠_第2頁
單片機(jī)原理及應(yīng)用李建忠_第3頁
單片機(jī)原理及應(yīng)用李建忠_第4頁
單片機(jī)原理及應(yīng)用李建忠_第5頁
已閱讀5頁,還剩164頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

單片機(jī)原理及應(yīng)用李建忠第一頁,共一百六十九頁,2022年,8月28日7.1C語言與MCS–51用匯編程序設(shè)計(jì)MCS–51系列單片機(jī)應(yīng)用程序時,必須要考慮其存儲器結(jié)構(gòu),尤其必須考慮其片內(nèi)數(shù)據(jù)存儲器與特殊功能寄存器正確、合理的使用以及按實(shí)際地址處理端口數(shù)據(jù)。用C語言編寫MCS–51單片機(jī)的應(yīng)用程序,雖然不像用匯編語言那樣具體地組織、分配存儲器資源和處理端口數(shù)據(jù),但在C語言編程中,對數(shù)據(jù)類型與變量的定義,必須要與單片機(jī)的存儲結(jié)構(gòu)相關(guān)聯(lián),否則編譯器不能正確地映射定位。用C語言編寫單片機(jī)應(yīng)用程序與編寫標(biāo)準(zhǔn)的C語言程序的不同之處就在于根據(jù)單片機(jī)存儲結(jié)構(gòu)及內(nèi)部資源定義相應(yīng)的C語言中的數(shù)據(jù)類型和變量,其它的語法規(guī)定、程序結(jié)構(gòu)及程序設(shè)計(jì)方法都與標(biāo)準(zhǔn)的C語言程序設(shè)計(jì)相同。第二頁,共一百六十九頁,2022年,8月28日用C語言編寫的應(yīng)用程序必須經(jīng)單片機(jī)的C語言編譯器(簡稱C51),轉(zhuǎn)換生成單片機(jī)可執(zhí)行的代碼程序。支持MCS–51系列單片機(jī)的C語言編譯器有很多種。如AmericanAutomation、Auocet、BSO/TASKING、DUNFIELDSHAREWARE、KEIL/Franklin等。其中KEIL/Franklin以它的代碼緊湊和使用方便等特點(diǎn)優(yōu)于其它編譯器。本章是針對這種編譯器介紹MCS–51單片機(jī)C語言程序設(shè)計(jì)。第三頁,共一百六十九頁,2022年,8月28日7.2C51數(shù)據(jù)類型及在MCS-51中的存儲方式7.2.1C51的數(shù)據(jù)類型FranklinC51編譯器具體支持的數(shù)據(jù)類型有:位型(bit)、無符號字符(unsignedchar)、有符號字符(singedchar)、無符號整型(unsignedint)、有符號整型(signedint)、無符號長整型(unsignedlong)、有符號長整型(signedlong)、浮點(diǎn)型(float)和指針類型等。第四頁,共一百六十九頁,2022年,8月28日表7.1FranklinC51的數(shù)據(jù)類型數(shù)據(jù)類型長度(bit)長度(byte)值域bit110,1unsignedchar810~255signedchar81–128~127unsignedint1620~65535signedint162–32768~32767unsignedlong3240~4294967295signedlong324–2147483648~2147483647float324±1.176E–38~±3.40E+38(6位數(shù)字)double648±1.176E–38~±3.40E+38(10位數(shù)字)一般指針243存儲空間0~65535第五頁,共一百六十九頁,2022年,8月28日7.2.2C51數(shù)據(jù)在MCS-51中的存儲方式位變量(bit):與MCS-51硬件特性操作有關(guān)的可以定義成位變量。位變量必須定位在MCS-51單片機(jī)片內(nèi)RAM的位尋址空間中。字符變量(char):字符變量的長度為1byte即8位。這很合適MCS-51單片機(jī),因?yàn)镸CS-51單片機(jī)每次可處理8位數(shù)據(jù)。對于無符號變量(unsignedchar)的值域范圍是0~255。對于有符號字符變量(signedchar),最具有重要意義的位是最高位上的符號標(biāo)志位(msb)。此位為1代表"負(fù)",為0代表"正"。有符號字符變量和無符號字符變量在表示0~127的數(shù)值時,其含義是一樣的,都是0~0x7F。負(fù)數(shù)一般用補(bǔ)碼表示,即用11111111表示-1,用11111110表示-2……。當(dāng)進(jìn)行乘除法運(yùn)算時,符號問題就變得十分復(fù)雜,而C51編譯器會自動地將相應(yīng)的庫函數(shù)調(diào)入程序中來解決這個問題。第六頁,共一百六十九頁,2022年,8月28日整型變量(int):整型變量的長度為16位。與8080和8086CPU系列不同,MCS-51系列單片機(jī)將int型變量的高位字節(jié)數(shù)存放在低地址字節(jié)中,低位字節(jié)數(shù)存放在高地址字節(jié)中。有符號整型變量(signedint)也使用msb位作符號標(biāo)志位,并使用二進(jìn)制補(bǔ)碼表示數(shù)值??芍苯邮褂脦追N專用的機(jī)器指令來完成多字節(jié)的加、減、乘、除運(yùn)算。整型變量值0x1234以圖7.1所示的方式存放在內(nèi)存中。第七頁,共一百六十九頁,2022年,8月28日圖7.1整型數(shù)的存儲結(jié)構(gòu)…0x120x34…+0+1地址0x120x340x560x78….+0+1+2+3地址圖7.2長整型變量的存儲結(jié)構(gòu)第八頁,共一百六十九頁,2022年,8月28日浮點(diǎn)型變量(float):浮點(diǎn)型變量為32位,占4個字節(jié),許多復(fù)雜的數(shù)學(xué)表達(dá)式都采用浮點(diǎn)變量數(shù)據(jù)類型。應(yīng)用符號位表示數(shù)的符號,用階碼和尾數(shù)表示數(shù)的大小。用它們進(jìn)行任何數(shù)學(xué)運(yùn)算都需要使用由編譯器決定的各種不同效率等級的庫函數(shù)。FranklinC51的浮點(diǎn)變量數(shù)據(jù)類型的使用格式與IEEE-754標(biāo)準(zhǔn)有關(guān),具有24位精度,尾數(shù)的高位始終為"1",因而不保存,位的分布如下:●1位符號位?!?位指數(shù)位。●23位尾數(shù)。第九頁,共一百六十九頁,2022年,8月28日符號位是最高位,尾數(shù)為低23位,內(nèi)存中按字節(jié)存儲順序如下:地址+0+1+2+3內(nèi)容MMMMMMMMMMMMMMMMEMMMMMMMSEEEEEEE其中,S為符號位,1表示負(fù),0表示正;E為階碼;M為23位尾數(shù),最高位為"1"。浮點(diǎn)變量值-12.5的十進(jìn)制為:0xC1480000,它按圖7.3所示方式存于內(nèi)存中。第十頁,共一百六十九頁,2022年,8月28日0x000x000x480xC1….+0+1+2+3地址圖7.3浮點(diǎn)數(shù)的存儲結(jié)構(gòu)第十一頁,共一百六十九頁,2022年,8月28日在編程時,如果只強(qiáng)調(diào)運(yùn)算速度而不進(jìn)行負(fù)數(shù)運(yùn)算時,最好采用無符號(unsigned)格式。無符號字符類型的使用:無論何時,應(yīng)盡可能使用無符號字符變量,因?yàn)樗苤苯颖籑CS-51所接受。基于同樣的原因,也應(yīng)盡量使用位變量。有符號字符變量雖然也只占用一個字節(jié),但需要進(jìn)行額外的操作來進(jìn)行測試代碼的符號位。這無疑會降低代碼效率。第十二頁,共一百六十九頁,2022年,8月28日使用簡化形式定義數(shù)據(jù)類型。其方法是在源程序開頭使用#define語句自定義簡化的類型標(biāo)識符。例如:#defineucharunsignedchar#defineuintunsignedint這樣,在編程中,就可以用uchar代替unsignedchar,用uint代替unsignedint來定義變量。第十三頁,共一百六十九頁,2022年,8月28日7.3C51數(shù)據(jù)的存儲類型與MCS-51存儲結(jié)構(gòu)表7.2C51存儲類型與MCS-51存儲空間的對應(yīng)關(guān)系存儲類型與存儲空間的對應(yīng)關(guān)系data直接尋址片內(nèi)數(shù)據(jù)存儲區(qū),訪問速度快(128字節(jié))bdata可位尋址片內(nèi)數(shù)據(jù)存儲區(qū),允許位與字節(jié)混合訪問(16字節(jié))idata間接尋址片內(nèi)數(shù)據(jù)存儲區(qū),可訪問片內(nèi)全部RAM地址空間(256字節(jié))pdata分頁尋址片外數(shù)據(jù)存儲區(qū)(256字節(jié))由MOV@Ri訪問(i=0,1)xdata片外數(shù)據(jù)存儲區(qū)(64KB)由MOVX@DPTR訪問code程序存儲器64KB空間,由MOVC@DPTR訪問第十四頁,共一百六十九頁,2022年,8月28日表7.3C51存儲類型及其數(shù)據(jù)長度和值域存儲類型長度(bit)長度(byte)值域范圍data810~255idata810~255pdata810~255xdata1620~65535code1620~65535第十五頁,共一百六十九頁,2022年,8月28日帶存儲類型的變量的定義的一般格式為數(shù)據(jù)類型存儲類型變量名帶存儲類型的變量定義舉例:chardatavar1;bitbdataflags;floatidatax,y,z;unsignedintpdatavar2;unsignedcharvector[3][4];第十六頁,共一百六十九頁,2022年,8月28日表7.4存儲模式說明存儲模式說明SMALL默認(rèn)的存儲類型是data,參數(shù)及局部變量放入可直接尋址片內(nèi)RAM的用戶區(qū)中(最大128字節(jié))。另外所有對象(包括堆棧),都必須嵌入片內(nèi)RAM。棧長很關(guān)鍵,因?yàn)閷?shí)際棧長依賴于函數(shù)嵌套調(diào)用層數(shù)COMPACT默認(rèn)的存儲類型是pdata,參數(shù)及局部變量放入分頁的外部數(shù)據(jù)存儲區(qū),通過@R0或@R1間接訪問,??臻g位于片內(nèi)數(shù)據(jù)存儲區(qū)中LARGE默認(rèn)的存儲類型是xdata,參數(shù)及局部變量直接放入片外數(shù)據(jù)存儲區(qū),使用數(shù)據(jù)指針DPTR來進(jìn)行尋址。用此數(shù)據(jù)指針進(jìn)行訪問效率較低,尤其對兩個或多個字節(jié)的變量,這種數(shù)據(jù)類型的訪問機(jī)制直接影響代碼的長度第十七頁,共一百六十九頁,2022年,8月28日7.4MCS-51特殊功能寄存器(SFR)的C51定義MCS-51單片機(jī)中,除了程序計(jì)數(shù)器PC和4組工作寄存器組外,其它所有的寄存器均為特殊功能寄存器(SFR),分散在片內(nèi)RAM區(qū)的高128字節(jié)中,地址范圍為80H~0FFH。SFR中有11個寄存器具有位尋址能力,它們的字節(jié)地址都能被8整除,即字節(jié)地址是以8或0為尾數(shù)的。為了能直接訪問這些SFR,F(xiàn)ranklinC51提供了一種自主形式的定義方法,這種定義方法與標(biāo)準(zhǔn)C語言不兼容,只適用于對MCS-51系列單片機(jī)進(jìn)行C語言編程。特殊功能寄存器C51定義的一般語法格式如下: sfrsfr-name=intconstant;第十八頁,共一百六十九頁,2022年,8月28日"sfr"是定義語句的關(guān)鍵字,其后必須跟一個MSC-51單片機(jī)真實(shí)存在的特殊功能寄存器名,"="后面必須是一個整型常數(shù),不允許帶有運(yùn)算符的表達(dá)式,是特殊功能寄存器"sfr-name"的字節(jié)地址,這個常數(shù)值的范圍必須在SFR地址范圍內(nèi),位于0x80~0xFF。例如:sfrSCON=0x98; /*串口控制寄存器地址98H*/sfrTMOD=0x89; /*定時器/計(jì)數(shù)器方式控制寄存器地址89H*/第十九頁,共一百六十九頁,2022年,8月28日MCS-51系列單片機(jī)的特殊功能寄存器的數(shù)量與類型不盡相同,因此建議將所有特殊的"sfr"定義放入一個頭文件中,該文件應(yīng)包括MCS-51單片機(jī)系列機(jī)型中的SFR定義。C51編譯器的"reg51.h"頭文件就是這樣一個文件。在新的MCS-51系列產(chǎn)品中,SFR在功能上經(jīng)常組合為16位值,當(dāng)SFR的高字節(jié)地址直接位于低字節(jié)之后時,對16位SFR的值可以直接進(jìn)行訪問。例如52子系列的定時器/計(jì)數(shù)器2就是這種情況。為了有效地訪問這類SFR,可使用關(guān)鍵字"sfr16"來定義,其定義語句的語法格式與8位SFR相同,只是"="后面的地址必須用16位SFR的低字節(jié)地址,即低字節(jié)地址作為"sfr16"的定義地址。第二十頁,共一百六十九頁,2022年,8月28日例如:sfr16T2=0xCC /*定時器/計(jì)數(shù)器2:T2低8位地址為0CCH,T2高8位地址為0CDH*/這種定義適用于所有新的16位SFR,但不能用于定時器/計(jì)數(shù)器0和1。對于位尋址的SFR中的位,C51的擴(kuò)充功能支持特殊位的定義,像SFR一樣不與標(biāo)準(zhǔn)C兼容,使用"sbit"來定義位尋址單元。第二十一頁,共一百六十九頁,2022年,8月28日第一種格式:sbitbit-name=sfr-name^intconstant;"sbit"是定義語句的關(guān)鍵字,后跟一個尋址位符號名(該位符號名必須是MCS-51單片機(jī)中規(guī)定的位名稱),"="后的"sfr-name"必須是已定義過的SFR的名字,"^"后的整常數(shù)是尋址位在特殊功能寄存器"sfr-name"中的位號,必須是0~7范圍中的數(shù)。例如:sfrPSW=0xD0; /*定義PSW寄存器地址為D0H*/sbitOV=PSW^2; /*定義OV位為PSW.2,地址為D2H*/sbitCY=PSW^7; /*定義CY位為PSW.7,地址為D7H*/第二十二頁,共一百六十九頁,2022年,8月28日第二種格式:sbitbit-name=intconstant^intconstant;"="后的intconstant為尋址地址位所在的特殊功能寄存器的字節(jié)地址,"^"符號后的intconstant為尋址位在特殊功能寄存器中的位號。例如:sbitOV=0XD0^2; /*定義OV位地址是D0H字節(jié) 中的第2位*/sbitCY=0XD0^7; /*定義CY位地址是D0H字節(jié)中 的第7位*/第二十三頁,共一百六十九頁,2022年,8月28日第三種格式:sbitbit-name=intconstant;"="后的intconstant為尋址位的絕對位地址。例如:sbitOV=0XD2; /*定義OV位地址為D2H*/sbitCY=0XD7; /*定義CY位地址為D7H*/特殊功能位代表了一個獨(dú)立的定義類,不能與其它位定義和位域互換。第二十四頁,共一百六十九頁,2022年,8月28日7.5MCS-51并行接口的C51定義MCS-51系列單片機(jī)并行I/O接口除了芯片上的4個I/O口(P0~P3)外,還可以在片外擴(kuò)展I/O口。MCS-51單片機(jī)I/O口與數(shù)據(jù)存儲器統(tǒng)一編址,即把一個I/O口當(dāng)作數(shù)據(jù)存儲器中的一個單元來看待。使用C51進(jìn)行編程時,MCS-51片內(nèi)的I/O口與片外擴(kuò)展的I/O可以統(tǒng)一在一個頭文件中定義,也可以在程序中(一般在開始的位置)進(jìn)行定義,其定義方法如下:對于MCS-51片內(nèi)I/O口按特殊功能寄存器方法定義。例如:sfrP0=0x80;/*定義P0口,地址為80H*/sfrP1=0x90;/*定義P1口,地址為90H*/第二十五頁,共一百六十九頁,2022年,8月28日對于片外擴(kuò)展I/O口,則根據(jù)硬件譯碼地址,將其視作為片外數(shù)據(jù)存儲器的一個單元,使用#define語句進(jìn)行定義。例如#include<absacc.h>#definePORTAXBYTE[0xFFC0]absacc.h是C51中絕對地址訪問函數(shù)的頭文件,將PORTA定義為外部I/O口,地址為FFC0H,長度為8位。一旦在頭文件或程序中對這些片外I/O口進(jìn)行定義后,在程序中就可以自由使用變量名與其實(shí)際地址的聯(lián)系,以便使程序員能用軟件模擬MCS-51的硬件操作。第二十六頁,共一百六十九頁,2022年,8月28日(1)位變量C51定義。使用C51編程時,定義了位變量后,就可以用定義了的變量來表示MCS-51的位尋址單元。位變量的C51定義的一般語法格式如下:位類型標(biāo)識符(bit)位變量名;例如:bitdirection_bit; /*把direction_bit定義為位變量*/bitlook_pointer; /*把look_pointer定義為位變量*/7.6位變量的C51定義第二十七頁,共一百六十九頁,2022年,8月28日(2)函數(shù)可包含類型為"bit"的參數(shù),也可以將其作為返回值。例如:

bitfunc(bitb0,bitb1) /*變量b0,b1作為函數(shù)的參數(shù)*/{return(b1); /*變量b1作為函數(shù)的返回值*/}注意,使用(#pragmadisable)或包含明確的寄存器組切換(usingn)的函數(shù)不能返回位值,否則編輯器將會給出一個錯誤信息。…第二十八頁,共一百六十九頁,2022年,8月28日(3)對位變量定義的限制。位變量不能定義成一個指針,如不能定義:bit*bit_pointer。不存在位數(shù)組,如不能定義:bitb_array[]。在位定義中,允許定義存儲類型,位變量都被放入一個位段,此段總位于MCS-51片內(nèi)的RAM區(qū)中。因此,存儲類型限制為data和idata,如果將位變量的存儲類型定義成其它存儲類型都將編譯出錯。第二十九頁,共一百六十九頁,2022年,8月28日例1先定義變量的數(shù)據(jù)類型和存儲類型:bdataintibase; /*定義ibase為bdata整型變量*/bdatacharbary[4]; /*bary[4]定義為bdata字符型數(shù)組*/然后可使用"sbit"定義可獨(dú)立尋址訪問的對象位:sbitmybit0=ibase^0; /*mybit0定義為ibase的第0位*/sbitmybit15=ibase^15; /*mybit0定義為ibase的第15位*/sbitAry07=bary[0]^7; /*Ary07定義為abry[0]的第7位*/sbitAry37=bary[3]^7; /*Ary37定義為abry[3]的第7位*/第三十頁,共一百六十九頁,2022年,8月28日對象ibase和bary也可以字節(jié)尋址:ary37=0; /*bary[3]的第7位賦值為0*/bary[3]='a'; /*字節(jié)尋址,bary[3]賦值為'a'*/sbit定義要位尋址對象所在字節(jié)基址對象的存儲類型為"bdata",否則只有絕對的特殊位定義(sbit)是合法的。"^"操作符后的最大值依賴于指定的基類型,對于char/uchar而言是0~7,對于int/uint而言是0~15,對于long/ulong而言是0~31。第三十一頁,共一百六十九頁,2022年,8月28日7.7C51構(gòu)造數(shù)據(jù)類型1.基于存儲器的指針基于存儲器的指針以存儲器類型為參量,它在編譯時才被確定。因此,為指針選擇存儲器的方法可以省掉,以便這些指針的長度為一個字節(jié)(idata*,data*,pdata*)或2個字節(jié)(code*,xdata*)。編譯時,這類操作一般被"行內(nèi)"(inline)編碼,而無需進(jìn)行庫調(diào)用?;诖鎯ζ鞯闹羔樁x舉例:charxdata*px;第三十二頁,共一百六十九頁,2022年,8月28日在xdata存儲器中定義了一個指向字符型(char)的指針變量px。指針自身在默認(rèn)存儲區(qū)(決定于編譯模式),長度為2個字節(jié)(值為0~0xFFFF)。charxdata*datapdx;除了明確定義指針位于MCS-51內(nèi)部存儲區(qū)(data)外,其它與上例相同,它與編譯模式無關(guān)。datacharxdata*pdx;第三十三頁,共一百六十九頁,2022年,8月28日structtime{charhour;charmin;charsec;structtimexdata*pxtime;}在結(jié)構(gòu)structtime中,除了其它結(jié)構(gòu)成員外,還包含有一個具有和structtime相同的指針pxtime,time位于外部數(shù)據(jù)存儲器(xdata),指針pxtime具有兩個字節(jié)長度。第三十四頁,共一百六十九頁,2022年,8月28日structtimeidata*ptime;這個聲明定義了一個位于默認(rèn)存儲器中的指針,它指向結(jié)構(gòu)time,time位于idata存儲器中,結(jié)構(gòu)成員可以通過MCS-51的@R0或@R1進(jìn)行間接訪問,指針ptime為1個字節(jié)長。ptime→pxtime→hour=12;使用上面的關(guān)于structtime和structidata*ptime的定義,指針"pxtime"被從結(jié)構(gòu)中間接調(diào)用,它指向位于xdata存儲器中的time結(jié)構(gòu)。結(jié)構(gòu)成員hour被賦值為12。第三十五頁,共一百六十九頁,2022年,8月28日2.一般指針一般指針包括3個字節(jié):1個字節(jié)存儲類型和2個字節(jié)偏移地址,即地址+0+1+2內(nèi)容存儲器類型偏移地址高位字節(jié)偏移地址低位字節(jié)其中,第一字節(jié)代表了指針的存儲器類型,存儲器類型編碼如下:存儲器類型idataxdatapdatadatacode值12345第三十六頁,共一百六十九頁,2022年,8月28日例如,以xdata類型的0x1234地址為指針可以表示如下:地址+0+1+2內(nèi)容0x020x120x34當(dāng)用常數(shù)作指針時,必須注意正確定義存儲器類型和偏移量。例如,將常數(shù)值0x41寫入地址為0x8000的外部數(shù)據(jù)存儲器。

#defineXBYTE((char*)0x20000L)XBYTE[0x8000]=0x41;其中,XBYTE被定義為(char*)0x20000L,0x20000L為一般指針,其存儲類型為2,偏移量為0000H,這樣XBYTE成為指向xdata零地址的指針。而XBYTE[8000]則是外部數(shù)據(jù)存儲器的0x8000絕對地址。第三十七頁,共一百六十九頁,2022年,8月28日7.8模塊化程序開發(fā)過程圖7.4程序開發(fā)過程第三十八頁,共一百六十九頁,2022年,8月28日7.8.1混合編程1.命名規(guī)則表7.5函數(shù)名的轉(zhuǎn)換說明符號名轉(zhuǎn)換規(guī)則voidfunc(void)FUNC無參數(shù)傳遞或不含寄存器參數(shù)的函數(shù)名不作改變轉(zhuǎn)入目標(biāo)文件中,名字只是簡單地轉(zhuǎn)換為大寫形式voidfunc(void)_FUNC帶寄存器參數(shù)的函數(shù)名加入“_”字符前綴,表明這類函數(shù)包含寄存器的參數(shù)傳遞voidfunc(void)reentrant_?FUNC對于重入函數(shù)加上“_?”字符串前綴,表明這類函數(shù)包含棧內(nèi)的參數(shù)傳遞第三十九頁,共一百六十九頁,2022年,8月28日例2用匯編語言編寫函數(shù)"toupper",參數(shù)傳遞發(fā)生在寄存器R7中。UPPERSEGMENTCODE ;程序段PUBLIC_TOUPPER ;入口地址PSEGUPPER ;程序段_TOUPPER:MOVA,R7 ;從R7中取參數(shù) CJNEA,#'a',$+3JCUPPERETCJNEA,#'z'+1,$+3JNCUPPERETCLRACC,5UPPERET:MOVR7,A ;返回值放在R7中RET ;返回到C第四十頁,共一百六十九頁,2022年,8月28日2.參數(shù)傳遞規(guī)則表7.6參數(shù)傳遞的寄存器選擇參數(shù)類型charintlong,float一般指針第1個參數(shù)R7R6,R7R4~R7R1,R2,R3第2個參數(shù)R5R4,R5R4~R7R1,R2,R3第3個參數(shù)R3R2,R3無R1,R2,R3第四十一頁,共一百六十九頁,2022年,8月28日func1(inta)"a"是第一個參數(shù),在R6,R7中傳遞。func2(intb,intc,int*d)"b"是第一個參數(shù),在R6,R7中傳遞;"c"是第二個參數(shù),在R4,R5中傳遞;"d"是第三個參數(shù),在R1,R2,R3中傳遞。func3(longe,longf)"e"是第一個參數(shù),在R4~R7中傳遞;"f"是第二個參數(shù),不能在寄存器中傳遞,只能在參數(shù)傳遞段中傳遞。func4(floatg,charh)"g"是第一個參數(shù),在R4~R7中傳遞;"h"是第二個參數(shù),必須在參數(shù)傳遞段中傳遞。第四十二頁,共一百六十九頁,2022年,8月28日表7.7函數(shù)返回值的寄存器返回值寄存器說明bitC進(jìn)位標(biāo)位(unsigned)charR7

(unsigned)intR6,R7高位字節(jié)在R6,低位字節(jié)在R7(unsigned)longR4~R7高位字節(jié)在R4,低位字節(jié)在R7floatR4~R732位IEEE格式,指數(shù)和符號位在R7指針R1,R2,R3R3放存儲器類型,高位在R2,低位在R1第四十三頁,共一百六十九頁,2022年,8月28日在匯編子程序中,當(dāng)前選擇的寄存器組及寄存器ACC、B、DPTR和PSW都可能改變。當(dāng)被C調(diào)用時,必須無條件地假設(shè)這些寄存器的內(nèi)容已被破壞。如果已在連接/定位程序時選擇了覆蓋,那么每個匯編子程序包含一個單獨(dú)的程序段是必要的,因?yàn)樵诟采w過程中,函數(shù)間參量通過子程序各自的段參量計(jì)算。匯編子程序的數(shù)據(jù)區(qū)甚至可包含在覆蓋部分中,但應(yīng)注意下面兩點(diǎn):(1)所有段名必須以C51類似的方法建立。(2)每個有局部變量的匯編程序必須指定自己的數(shù)據(jù)段,這個數(shù)據(jù)段只能為其它函數(shù)訪問作參數(shù)傳遞用。所有參數(shù)一個接一個被傳遞,由其它函數(shù)計(jì)算的結(jié)果保存入棧。第四十四頁,共一百六十九頁,2022年,8月28日7.8.2覆蓋和共享1.覆蓋單片機(jī)片內(nèi)存儲空間有限,連接器/定位器通常重新啟用程序不再用的位置。這就是說,若一個程序不再調(diào)用,也不由其它程序調(diào)用(甚至間接調(diào)用),那么在其它程序執(zhí)行完之前,這個程序不再運(yùn)行。這個程序的變量可以放在與其它程序完全相同的RAM空間,很像可重用的寄存器。這種技術(shù)就是覆蓋。在匯編中直接通過手工完成的這些空間分配,C語言中可以由連接器自動管理。若有幾個不相關(guān)聯(lián)的程序時,它可以使RAM單元比手工考慮要用的少。第四十五頁,共一百六十九頁,2022年,8月28日2.共享1)共享變量類型匯編語言C語言動態(tài)變量

y(){intx;}靜態(tài)變量

staticintx;公用變量PUBLICXX:ds2Intx;外部變量EXTERNDATA(X)MOVDPTR,#Xexternintx;靜態(tài)子程序/函數(shù)Y:…staticy(){…};公共子程序/函數(shù)PUBLICYY:y(){…};外部子程序/函數(shù)EXTERNCODE(Y)LCALLYy()第四十六頁,共一百六十九頁,2022年,8月28日2)共享函數(shù)/子程序C中函數(shù)若是全局的(公用的),可以放在調(diào)用的函數(shù)之后。若函數(shù)是模塊專用的,它可以定義為靜態(tài)函數(shù),這樣它不能被其它模塊調(diào)用。C語言的ANSI標(biāo)準(zhǔn)建議所有函數(shù)在主函數(shù)前要有原型(進(jìn)行說明),然后實(shí)際函數(shù)可在主函數(shù)之后或其它模塊中。這符合自頂向下編程的概念。匯編語言中,子程序使用標(biāo)號可在給定模塊的任何位置。匯編器首先掃描得到所有的符號名,然后值就可填入LCALL或LJMP。一個模塊或另一模塊共享子程序,一個使用PUBLIC而另一個使用EXTERN。當(dāng)指定為EXTERN,符號類型(CODE,DATA,XDATA,IDATA,BIT或NUMBER)必須特別加以指定,以便連接器可以確定放在一起的正確類型。第四十七頁,共一百六十九頁,2022年,8月28日7.8.3庫和連接器/定位器1.庫表7.9FranklinC51的編譯庫庫說明C51S.LIBSMALL模式,無浮點(diǎn)運(yùn)算C51FPS.LIB浮點(diǎn)數(shù)學(xué)運(yùn)算庫(SMALL模式)C51C.LIBCOMPACT模式,無浮點(diǎn)運(yùn)算C51FPC.LIB浮點(diǎn)運(yùn)算庫(COMPACT模式)C51L.LIBLARGE模式,無浮點(diǎn)運(yùn)算C51FPL.LIB浮點(diǎn)運(yùn)算庫(LARGE模式)第四十八頁,共一百六十九頁,2022年,8月28日2.連接器/定位器1)組合程序模塊將幾個不同程序模塊組合為一個模塊,并自動從庫中挑選模塊嵌入目標(biāo)文件。輸入文件按命令行中出現(xiàn)的順序處理。通常的程序模塊是由C51編譯器或A51宏匯編生成的可重入的目標(biāo)文件。第四十九頁,共一百六十九頁,2022年,8月28日2)組合段將具有相同段名的可重定位段組合成單一的段。在一個程序模塊中定義的一個段成為部分段。一個部分段在源文件中以下列形式指定:(1)名字每個重定位段有一個名字,它可與來自其它模塊的同名的可重定位段組合。絕對段沒有名字。(2)類型類型表明段所屬的地址空間CODE,XDATA,DATA或BIT。第五十頁,共一百六十九頁,2022年,8月28日(3)定位方式可重定位段的定位方式有PAGE,INPAGE,INBLOCK,BITADDRESSABLE或UNIT。INPAGE表明段必須放入一頁(高8位地址相同)中以使用短轉(zhuǎn)移和調(diào)用指令。INBLOCK段應(yīng)使用ACALL,必須放在2048字節(jié)塊中。因?yàn)闆]有連接器可以靈活地判知調(diào)用和轉(zhuǎn)移是否在塊內(nèi)。可重定位的其它限制是:不能超過256字節(jié);BITADDRESSABLE--必須放在可位尋址的內(nèi)部RAM空間;UNIT--允許段從任意字節(jié)開始(對位變量是位)。(4)長度一個段的長度。第五十一頁,共一百六十九頁,2022年,8月28日(5)基址段的首址。對于絕對段,地址由匯編器賦予,對于可重定位段,地址由L51決定。在處理程序模塊時,L51自動產(chǎn)生段表(MAP),該表包含了每個段的類型、基址、長度、可重定位性和名字。L51自動將所具有相同名字的所有部分段組合到單一可重定位段中。例如,三個程序模塊包含字段VAR,在組合時,三個段的長度相加,從而組合段的長度也增加了。對組合段有下列規(guī)則:①所有具有相同名的部分段必須有相同類型(CODE,DATA,IDATA,XDATA或BIT)。②組合段的長度不能超過存儲區(qū)的物理長度。③每個組合的部分段的定位方法也必須相同。④絕對段相互不組合,它們被直接拷貝到輸出文件。第五十二頁,共一百六十九頁,2022年,8月28日3)存儲器分配物理存儲區(qū)最大長度地址區(qū)段類型程序64KB0~0FFFFHCODE外部數(shù)據(jù)64KB0~0FFFFHXDATA直接尋址片內(nèi)數(shù)據(jù)128字節(jié)0~7FHDATA間接尋址片內(nèi)數(shù)據(jù)256字節(jié)0~0FFHIDATA片內(nèi)數(shù)據(jù)的位空間128位0~7FHBIT表7.10MCS-51系列的物理存儲區(qū)第五十三頁,共一百六十九頁,2022年,8月28日4)采用覆蓋技術(shù)使用數(shù)據(jù)存儲器通過采用一定的覆蓋技術(shù),MCS-51系列少量的片內(nèi)數(shù)據(jù)存儲器可由L51有效地使用。由C51編譯器或是A51匯編器生成的參數(shù)和局部變量(若使用它們的函數(shù)不相互調(diào)用)可在存儲器中覆蓋。這樣,所用的存儲器得到相當(dāng)程度地減少。為完成數(shù)據(jù)覆蓋,L51分析所有不同函數(shù)間的調(diào)用,使用該信息可以確定哪個數(shù)據(jù)和位段可被覆蓋。使用控制參數(shù)OVERLAY和NOOVERLAY可允許或禁止覆蓋。OVERLAY是默認(rèn)值,用它可產(chǎn)生非常緊湊的數(shù)據(jù)區(qū)。第五十四頁,共一百六十九頁,2022年,8月28日5)決定外部參考地址具有相同名的外部符號(EXTERN)和公用符號(PUBLIC)被確定后,外部符號指向其它模塊中的地址。一個已聲明的外部符號用具有相同名字的功用符號確定,外部參考地址由其公共參考地址確定。這還與類型(DATA,IDATA,XDATA,CODE,BIT或NUMBER)有關(guān),如果類型不符或未發(fā)現(xiàn)外部符號參考地址的公用符號,則會產(chǎn)生錯誤。公用符號的絕對地址在段定位后決定。第五十五頁,共一百六十九頁,2022年,8月28日6)絕對地址計(jì)算定義絕對地址并計(jì)算可重定位段的地址。在段分配和外部公用參考地址處理完后,程序模塊中所有可重定位地址和外部地址要進(jìn)行計(jì)算,此時生成的目標(biāo)文件中的符號信息(DEBUG)被改變以反映新的值。第五十六頁,共一百六十九頁,2022年,8月28日7)產(chǎn)生絕對目標(biāo)文件可執(zhí)行程序以絕對目標(biāo)格式產(chǎn)生。該絕對目標(biāo)文件可包含附加的符號信息(DEBUG),從而使符號調(diào)試成為可能。符號信息可用參數(shù)NODEBUGSYMBOLS,NODEBUGPUBLICS和NODEBUGLINES禁止。輸出文件是可執(zhí)行的,并可由仿真器裝入調(diào)試或被OHS51翻譯為IntelHEX格式文件以供EPROM固化。第五十七頁,共一百六十九頁,2022年,8月28日8)產(chǎn)生映像文件產(chǎn)生一個反映每個處理步驟的映像文件,它顯示有關(guān)連接/定位過程的信息和程序符號,并包含一個公用和外部符號的交叉參考報告。映像文件包含下列信息:①文件名和命令行參數(shù)。②模塊的文件名和模塊名。③一個包含段地址、類型、定位方法和名字的存儲器分配表。該表可在命令行中用NOMAP參考禁止。第五十八頁,共一百六十九頁,2022年,8月28日④段和符號的所有錯誤列表。列表文件末尾顯示出所有出錯的原因。⑤一個包含輸入文件中符號信息的符號表。該信息由MODULES,SYMBOLS,PUBLICS和LINES名組成,LINES是C編譯器產(chǎn)生的行號。符號信息可用參數(shù)NOSYMBOLS,NOPUBLICS和NOLINES完全或部分禁止。⑥一個按字母順序排列的有關(guān)所有PUBLIC和EXTERN符號的交叉參考報告,其中顯示出符號類型和模塊名。第一個顯示的模塊名是定義了PUBLIC符號的模塊,后面的模塊名是定義了EXTERN符號的模塊。在命令行輸入?yún)?shù)IXREF可產(chǎn)生此報告。⑦在連接器/定位器運(yùn)行期間檢測到的錯誤同時顯示在屏幕和文件尾部。第五十九頁,共一百六十九頁,2022年,8月28日7.8.4程序優(yōu)化以下選擇對提高程序效率有很大影響:(1)盡量選擇小存儲模式以避免使用MOVX指令。(2)使用大模式(COMPACT/LARGE)應(yīng)仔細(xì)考慮要放在內(nèi)部數(shù)據(jù)存儲器的變量要求是經(jīng)常用的或是用于中間結(jié)果的。訪問內(nèi)部數(shù)據(jù)存儲器要比訪問外部數(shù)據(jù)存儲器快得多。內(nèi)部RAM由寄存器組、位數(shù)據(jù)區(qū)和其它用戶用“data”類型定義的變量共享。由于內(nèi)部RAM容量的限制(128~256字節(jié),由使用的單片機(jī)決定),必須權(quán)衡利弊以解決訪問效率和這些對象的數(shù)量之間的矛盾。第六十頁,共一百六十九頁,2022年,8月28日(3)要考慮操作順序,完成一件事后再做一件事。(4)注意程序編寫細(xì)則。例如,若使用for(;;)循環(huán),DJNZ指令比CJNE指令更有效,可減少重復(fù)循環(huán)次數(shù)。(5)若編譯器不能使用左移和右移完成乘除法,應(yīng)立即修改,例如,左移為乘2。(6)用邏輯AND/&取模比用MOD/%操作更有效。(7)因計(jì)算機(jī)基于二進(jìn)制,仔細(xì)選擇數(shù)據(jù)存儲器和數(shù)組大小可節(jié)省操作。第六十一頁,共一百六十九頁,2022年,8月28日(8)盡可能使用最小的數(shù)據(jù)類型,MCS-51系列是8位機(jī),顯然對具有"char"類型的對象的操作比"int"或"long"類型的對象的操作要方便得多。(9)盡可能使用"unsigned"數(shù)據(jù)類型。MCS-51系列CPU并不直接支持有符號數(shù)的運(yùn)算。因而C51編譯器必須產(chǎn)生與之相關(guān)的更多的程序代碼以解決這個問題。(10)盡可能使用局部函數(shù)變量。編譯器總是嘗試在寄存器里保持局部變量。這樣,將循環(huán)變量(如for和while循環(huán)中的計(jì)數(shù)變量)說明為局部變量是最好的。使用"unsignedchar/int"的對象通常能獲得最好的結(jié)果。第六十二頁,共一百六十九頁,2022年,8月28日7.9MCS-51內(nèi)部資源使用的C語言編程7.9.1中斷應(yīng)用的C語言編程C51編譯器支持在C源程序中直接開發(fā)中斷程序。中斷服務(wù)程序是通過按規(guī)定語法格式定義的一個函數(shù)。中斷服務(wù)程序的函數(shù)定義的語法格式如下:返回值函數(shù)名([參數(shù)])interruptm[usingn]{

}…第六十三頁,共一百六十九頁,2022年,8月28日表7.11MCS-51中斷源編號編號中斷源入口地址0外部中斷00003H1定時器/計(jì)數(shù)器0000BH2外部中斷10013H3定時器/計(jì)數(shù)器1001BH4串行口中斷0023H第六十四頁,共一百六十九頁,2022年,8月28日

usingn選項(xiàng)用于實(shí)現(xiàn)工作寄存器組的切換,n是中斷服務(wù)子程序中選用的工作寄存器組號(0~3)。在許多情況下,響應(yīng)中斷時需保護(hù)有關(guān)現(xiàn)場信息,以便中斷返回后,能使中斷前的源程序從斷點(diǎn)處繼續(xù)正確地執(zhí)行下去。這在MCS-51單片機(jī)中,能很方便地利用工作寄存器組的切換來實(shí)現(xiàn)。即在進(jìn)入中斷服務(wù)程序前的程序中使用一組工作寄存器,進(jìn)入中斷服務(wù)程序后,由"usingn"切換到另一組寄存器,中斷返回后又恢復(fù)到原寄存器組。這樣互相切換的兩組寄存器中的內(nèi)容彼此都沒有被破壞。第六十五頁,共一百六十九頁,2022年,8月28日圖7.5擴(kuò)展多個中斷源例3圖7.5所示是利用優(yōu)先權(quán)解碼芯片,在單片機(jī)8031的一個外部中斷INT1上擴(kuò)展多個中斷源的原理電路圖。圖中是以開關(guān)閉合來模擬中斷請求信號。當(dāng)有任一中斷源產(chǎn)生中斷請求,能給8031的INT1引腳送一個有效中斷信號,由P1的低3位可得對應(yīng)中斷源的中斷號。第六十六頁,共一百六十九頁,2022年,8月28日在中斷服務(wù)程序中僅設(shè)置標(biāo)志,并保存I/O口輸入狀態(tài)。FranklinC51編譯器提供定義特定MCS-51系列成員的寄存器頭文件。MCS-51頭文件為reg51.h。C51程序如下:#include<reg51.h>unsignedcharstatus;bitflag;voidservice_int1()interrupt2using2 /*INT1中斷服務(wù)程序,使用第2組工 作寄存器*/{flag=1; /*設(shè)置標(biāo)志*/status=p1; /*存輸入口狀態(tài)*/}voidmain(void){IP=0x04; /*置INT1為高優(yōu)先級中斷*/IE=-0x84; /*INT1開中斷,CPU開中斷*/第六十七頁,共一百六十九頁,2022年,8月28日for(;;){if(flag) /*有中斷*/{switch(status) /*根據(jù)中斷源分支*/{case0:break; /*處理IN0*/case1:break; /*處理IN1*/case2:break; /*處理IN2*/case3:break; /*處理IN3*/default:;}flag=0; /*處理完成清標(biāo)志*/}}}第六十八頁,共一百六十九頁,2022年,8月28日7.9.2定時器/計(jì)數(shù)器(T/C)應(yīng)用的C語言編程例4設(shè)單片機(jī)的fosc=12MHz晶振,要求在P1.0腳上輸出周期為2ms的方波。周期為2ms的方波要求定時時間隔1ms,每次時間到P1.0取反。機(jī)器周期=12/fosc=1μs需計(jì)數(shù)次數(shù)=1000/(12/fosc)=1000/1=1000由于計(jì)數(shù)器是加1計(jì)數(shù),為得到1000個計(jì)數(shù)之后的定時器溢出,必須給定時器置初值為-1000(即1000的補(bǔ)數(shù))。第六十九頁,共一百六十九頁,2022年,8月28日(1)用定時器0的方式1編程,采用查詢方式,程序如下:

#include<reg51.h>sbitP1_0=P1^0;voidmain(void){TMOD=0x01; /*設(shè)置定時器1為非門控制方式1*/TR0=1; /*啟動T/C0*/for(;;){TH0=-(1000/256); /*裝載計(jì)數(shù)器初值*/TL0=-(1000%256);do{}while(!TF0); /*查詢等待TF0置位*/P1_0=!P1_0; /*定時時間到P1.0反相*/TF0=0; /*軟件清TF0*/}}第七十頁,共一百六十九頁,2022年,8月28日(2)用定時器0的方式1編程,采用中斷方式。程序如下:#include<reg51.h>sbitP1_0=P1^0;voidtime(void)interrupt1using1/*T/C0中斷服務(wù)程序入口*/{P1_0=!P1_0; /*P1.0取反*/TH0=-(1000/256); /*重新裝載計(jì)數(shù)初值*/}voidmain(void){TMOD=0x01; /*T/C0工作在定時器非門控制方式1*/P1_0=0;TH0=-(1000/256); /*預(yù)置計(jì)數(shù)初值*/TL0=-(1000%256);EA=1; /*CPU中斷開放*/ET0=1; /*T/C0中斷開放*/TR0=1; /*啟動T/C0開始定時*/do{}while(1); /*等待中斷*/}第七十一頁,共一百六十九頁,2022年,8月28日例5采用10MHz晶振,在P1.0腳上輸出周期為2.5s,占空比20%的脈沖信號。10MHz晶振,使用定時器最大定時幾十毫秒。取10ms定時,周期2.5s需250次中斷,占空比20%,高電平應(yīng)為50次中斷。10ms定時,晶振fosc=10MHz。需定時器計(jì)數(shù)次數(shù)=10×103×10/12=8333#include<reg51.h>#defineucharunsignedcharucharperiod=250;ucharhigh=50;第七十二頁,共一百六十九頁,2022年,8月28日timer0()interrupt1using1 /*T/C0中斷服務(wù)程序*/{TH0=-8333/256; /*重置計(jì)數(shù)值*/TL0=-8333%256;if(++time==high)P1=0; /*高電平時間到變低*/elseif(time==period) /*周期時間到變高*/{time=0;P1=1;}}第七十三頁,共一百六十九頁,2022年,8月28日main(){TMOD=0x01; /*定時器0方式1*/TH0=-8333/256; /*預(yù)置計(jì)數(shù)初值*/TL0=-8333%256;EA=1; /*開CPU中斷*/ET0=1; /*開T/C0中斷*/TR0=1; /*啟動T/C0*/do{}while(1);}第七十四頁,共一百六十九頁,2022年,8月28日圖7.6中斷服務(wù)程序流程圖第七十五頁,共一百六十九頁,2022年,8月28日產(chǎn)生一個占空比變化脈沖信號的程序,它產(chǎn)生的脈寬調(diào)制信號用于電機(jī)變速控制。#include<reg51.h>#defineucharunsignedchar#defineuintunsignedintunchartime,status,percent,period;bitone_round;uintoldcount,target=500;voidpulse(void)interrupt1using1 /*T/C0中斷服務(wù)程序*/{TH0=-833/256; /*1ms--10MHz*/第七十六頁,共一百六十九頁,2022年,8月28日TL0=-833%256;ET0=1;if(++time=percent)P1=0;elseif(time==100){time=0;P1=1;}}voidtachmeter(void)interrupt2using2 /*外中斷1服務(wù)程序*/{union{unitword;struct{ucharhi;ucharlo;}byte;}第七十七頁,共一百六十九頁,2022年,8月28日newcount;newcount.byte.hi=TH1;newcount.byte.lo=TL1;period=newcount.word-oldcount;/*測得周期*/oldcount=newcount.word;one_round=1; /*每轉(zhuǎn)一圈,引起中斷,設(shè)置標(biāo)志*/}voidmain(void){IP=0x04; /*置INT1為高位優(yōu)先級*/TMOD=0x11; /*T0,T116位方式*/TCON=0x54; /*T0,T1運(yùn)行,IT1邊沿觸發(fā)*/第七十八頁,共一百六十九頁,2022年,8月28日TH1=0;TL1=0; /*設(shè)置初始計(jì)數(shù)值*/IE=0x86; /*允許中斷EX1,ET0*/for(;;){if(one_round) /*每轉(zhuǎn)一圈,調(diào)整*/{if(period<target){if(percent<100)++percent; /*占空比增*/}elseif(percent>0)--percent; /*占空比減*/one_round=0;}}}第七十九頁,共一百六十九頁,2022年,8月28日7.9.3串行口使用的C語言編程例6單片機(jī)fosc=11.0592MHz,波特率為9600,各設(shè)置32字節(jié)的隊(duì)列緩沖區(qū)用于發(fā)送接收。設(shè)計(jì)單片機(jī)和終端或另一計(jì)算機(jī)通信的程序。單片機(jī)串行口初始化成9600波特,中斷程序雙向處理字符,程序雙向緩沖字符。背景程序可以"放入"和"提取"在緩沖區(qū)的字符串,而實(shí)際傳入和傳出SBUF的動作由中斷完成。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請求。具體程序如下:第八十頁,共一百六十九頁,2022年,8月28日#include<reg51.h>#defineucharunsignedcharucharxdatar_buf[32]; /*item1*/ucharxdatat_buf[32];ucharr_in,r_out,t_in,t_done; /*隊(duì)列指針*/bitr_full,t_empty,t_done; /*item2*/codeucharm[]={"thisisatestprogram\r\n"};serial()interrupt4using1 /*item3*/{if(RI&&~r_full){r_buf[r_in]=SBUF;RI=0;第八十一頁,共一百六十九頁,2022年,8月28日r_in=++r_in&ox1f;if(r_in==r_out)r_full=1;}elseif(TI&&~t_empty){SBUF=t_buf[t_out];TI=0;t_out=++t_out&0x1f;if(t_out==t_in)t_empty=1;}elseif(TI){TI=0;t_done=1;}}第八十二頁,共一百六十九頁,2022年,8月28日voidloadmsg(ucharcode*msg) /*item4*/{while((*msg!=0)&&((((t_in+1)^t_out)&0x1f)!=0)) /*測試緩沖區(qū)滿*/{t_buf[t_in]=*msg;msg++;t_in=++t_in&0x1f;if(t_done){TI=1;t_empty=t_done=0; /*完成重新開始*/}}}第八十三頁,共一百六十九頁,2022年,8月28日voidprocess(ucharch){return;} /*item5*//*用戶定義*/voidprocessmsg(void) /*item6*/{while(((r_out+1)^r_in)!=0)/*接收非緩沖區(qū)*/{process(r_buf[r_out]);r_out=++r_out&0x1f;}}第八十四頁,共一百六十九頁,2022年,8月28日main() /*item7*/{TMOD=0x20; /*定時器1方式2*/TH1=0xfd; /*9600波特11.0592MHz*/TCON=0x40; /*啟動定時器1*/SCON=0x50; /*允許接收*/IE=0x90; /*允許串行口中斷*/t_empty=t_done=1;r_full=0;r_out=t_in=0;r_in=1; /*接收緩沖和發(fā)送緩沖置空*/for(;;){loadmsg(&m);processmsg();}}第八十五頁,共一百六十九頁,2022年,8月28日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)行串行口的初始化,載入字符串,處理接收的字符串。第八十六頁,共一百六十九頁,2022年,8月28日7.10MCS-51片外擴(kuò)展的C語言編程7.10.18255與8031接口C應(yīng)用程序舉例

例78255控制打印機(jī)。圖7.7是8031擴(kuò)展8255與打印機(jī)接口的電路。8255的片選線為P0.7,打印機(jī)與8031采用查詢方式交換數(shù)據(jù)。打印機(jī)的狀態(tài)信號輸入給PC7,打印機(jī)忙時BUSY=1,微型打印機(jī)的數(shù)據(jù)輸入采用選通控制,當(dāng)STB上負(fù)跳變時數(shù)據(jù)被輸入。8255采用方式0由PC0模擬產(chǎn)生STB信號。按照接口電路,口A地址為7CH,口C地址為7EH,命令口地址為7FH,PC7~PC4輸入,PC3~PC0輸出。方式選擇命令字為8EH。第八十七頁,共一百六十九頁,2022年,8月28日圖7.78031擴(kuò)展8255與打印機(jī)接口的電路第八十八頁,共一百六十九頁,2022年,8月28日向打印機(jī)輸出字符串"WELCOME"的程序如下:#include<absacc.h>#include<reg51.h>#defineucharunsignedchar#defineCOM8255XBYTE[0x007f] /*命令口地址*/#definePA8255XBYTE[0x007c] /*口A地址*/#definePC8255XBYTE[0x007e] /*口C地址*/voidtoprn(uchar*p) /*打印字符串函數(shù)*/{while(*p!='\0'){while((0x80&PC8255)!=0); /*查詢等待打印機(jī)的BUSY狀態(tài)*/第八十九頁,共一百六十九頁,2022年,8月28日PA8255=*p; /*輸出字符*/COM8255=0x00; /*模擬STB脈沖*/COM8255=0x01;p++;}}voidmain(void){ucharidataprn[]="WELCOME"; /*設(shè)測試用字符串*/COM8255=0x8e; /*輸出方式選擇命令*/toprn(prn); /*打印字符串*/}第九十頁,共一百六十九頁,2022年,8月28日例8EPROM編程器。由8031擴(kuò)展1片EPROM2716、2片SRAM6116及1片8255構(gòu)成EPROM編程器,編程對象是EPROM2732。擴(kuò)展編程系統(tǒng)中2716用來存放固化用監(jiān)控程序,用戶的待固化程序放在2片6116中。8255的口A作編程器數(shù)據(jù)口,口B輸出2732的低8位地址,PC3~PC0輸出2732高4位地址,PC7作2732啟動保持控制器與PGM連接。譯碼地址為:6116(1):0800H;6116(2):1000H~17FFH;8255的口A:07FCH;口B:07FDH;口C:07FEH;命令口:07FFH。第九十一頁,共一百六十九頁,2022年,8月28日8255的口A、口B、口C均工作在方式0輸出,方式選擇命令字為80H;2732的啟動編程和停止編程,由PC7的復(fù)位/置位控制,當(dāng)PC7=0時啟動編程,PC7=1時,編程無效。EPROM編程如下所示,參數(shù)為RAM起始地址、EPROM起始地址和編程字節(jié)數(shù)。#include<absacc.h>#include<reg51.h>#defineCOM8255XBYTE[0x07ff]#definePA8255XBYTE[0x07fc]#definePB8255XBYTE[0x07fd]#definePC8255XBYTE[0x07fe]#defineucharunsignedchar#defineuintunsignedint第九十二頁,共一百六十九頁,2022年,8月28日voidd1_ms(unitx);voidprogram(ram,eprom,con)ucharxdata*ram; /*RAM起始地址*/uinteprom,con; /*EPROM起始固化地址,固化長度*/{inti;COM8255=0x08; /*送方式選擇命令字*/COM8255=0x0f; /*PC7=1*/for(i=0;i<con;i++){PA8255=*ram; /*固化內(nèi)容口A鎖存*/PB8255=eprom%256; /*2732地址低8位*/PC8255=eprom/256; /*2732地址高4

溫馨提示

  • 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論