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

下載本文檔

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

文檔簡(jiǎn)介

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

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

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

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

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

usingn選項(xiàng)用于實(shí)現(xiàn)工作寄存器組的切換,n是中斷服務(wù)子程序中選用的工作寄存器組號(hào)(0~3)。在許多情況下,響應(yīng)中斷時(shí)需保護(hù)有關(guān)現(xiàn)場(chǎng)信息,以便中斷返回后,能使中斷前的源程序從斷點(diǎn)處繼續(xù)正確地執(zhí)行下去。這在MCS-51單片機(jī)中,能很方便地利用工作寄存器組的切換來(lái)實(shí)現(xiàn)。即在進(jìn)入中斷服務(wù)程序前的程序中使用一組工作寄存器,進(jìn)入中斷服務(wù)程序后,由"usingn"切換到另一組寄存器,中斷返回后又恢復(fù)到原寄存器組。這樣互相切換的兩組寄存器中的內(nèi)容彼此都沒(méi)有被破壞。第六十五頁(yè),共一百六十九頁(yè),2022年,8月28日?qǐng)D7.5擴(kuò)展多個(gè)中斷源例3圖7.5所示是利用優(yōu)先權(quán)解碼芯片,在單片機(jī)8031的一個(gè)外部中斷INT1上擴(kuò)展多個(gè)中斷源的原理電路圖。圖中是以開(kāi)關(guān)閉合來(lái)模擬中斷請(qǐng)求信號(hào)。當(dāng)有任一中斷源產(chǎn)生中斷請(qǐng)求,能給8031的INT1引腳送一個(gè)有效中斷信號(hào),由P1的低3位可得對(duì)應(yīng)中斷源的中斷號(hào)。第六十六頁(yè),共一百六十九頁(yè),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)先級(jí)中斷*/IE=-0x84; /*INT1開(kāi)中斷,CPU開(kāi)中斷*/第六十七頁(yè),共一百六十九頁(yè),2022年,8月28日f(shuō)or(;;){if(flag) /*有中斷*/{switch(status) /*根據(jù)中斷源分支*/{case0:break; /*處理IN0*/case1:break; /*處理IN1*/case2:break; /*處理IN2*/case3:break; /*處理IN3*/default:;}flag=0; /*處理完成清標(biāo)志*/}}}第六十八頁(yè),共一百六十九頁(yè),2022年,8月28日7.9.2定時(shí)器/計(jì)數(shù)器(T/C)應(yīng)用的C語(yǔ)言編程例4設(shè)單片機(jī)的fosc=12MHz晶振,要求在P1.0腳上輸出周期為2ms的方波。周期為2ms的方波要求定時(shí)時(shí)間隔1ms,每次時(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ù))。第六十九頁(yè),共一百六十九頁(yè),2022年,8月28日(1)用定時(shí)器0的方式1編程,采用查詢(xún)方式,程序如下:

#include<reg51.h>sbitP1_0=P1^0;voidmain(void){TMOD=0x01; /*設(shè)置定時(shí)器1為非門(mén)控制方式1*/TR0=1; /*啟動(dòng)T/C0*/for(;;){TH0=-(1000/256); /*裝載計(jì)數(shù)器初值*/TL0=-(1000%256);do{}while(!TF0); /*查詢(xún)等待TF0置位*/P1_0=!P1_0; /*定時(shí)時(shí)間到P1.0反相*/TF0=0; /*軟件清TF0*/}}第七十頁(yè),共一百六十九頁(yè),2022年,8月28日(2)用定時(shí)器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工作在定時(shí)器非門(mén)控制方式1*/P1_0=0;TH0=-(1000/256); /*預(yù)置計(jì)數(shù)初值*/TL0=-(1000%256);EA=1; /*CPU中斷開(kāi)放*/ET0=1; /*T/C0中斷開(kāi)放*/TR0=1; /*啟動(dòng)T/C0開(kāi)始定時(shí)*/do{}while(1); /*等待中斷*/}第七十一頁(yè),共一百六十九頁(yè),2022年,8月28日例5采用10MHz晶振,在P1.0腳上輸出周期為2.5s,占空比20%的脈沖信號(hào)。10MHz晶振,使用定時(shí)器最大定時(shí)幾十毫秒。取10ms定時(shí),周期2.5s需250次中斷,占空比20%,高電平應(yīng)為50次中斷。10ms定時(shí),晶振fosc=10MHz。需定時(shí)器計(jì)數(shù)次數(shù)=10×103×10/12=8333#include<reg51.h>#defineucharunsignedcharucharperiod=250;ucharhigh=50;第七十二頁(yè),共一百六十九頁(yè),2022年,8月28日timer0()interrupt1using1 /*T/C0中斷服務(wù)程序*/{TH0=-8333/256; /*重置計(jì)數(shù)值*/TL0=-8333%256;if(++time==high)P1=0; /*高電平時(shí)間到變低*/elseif(time==period) /*周期時(shí)間到變高*/{time=0;P1=1;}}第七十三頁(yè),共一百六十九頁(yè),2022年,8月28日main(){TMOD=0x01; /*定時(shí)器0方式1*/TH0=-8333/256; /*預(yù)置計(jì)數(shù)初值*/TL0=-8333%256;EA=1; /*開(kāi)CPU中斷*/ET0=1; /*開(kāi)T/C0中斷*/TR0=1; /*啟動(dòng)T/C0*/do{}while(1);}第七十四頁(yè),共一百六十九頁(yè),2022年,8月28日?qǐng)D7.6中斷服務(wù)程序流程圖第七十五頁(yè),共一百六十九頁(yè),2022年,8月28日產(chǎn)生一個(gè)占空比變化脈沖信號(hào)的程序,它產(chǎn)生的脈寬調(diào)制信號(hà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*/第七十六頁(yè),共一百六十九頁(yè),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;}第七十七頁(yè),共一百六十九頁(yè),2022年,8月28日newcount;newcount.byte.hi=TH1;newcount.byte.lo=TL1;period=newcount.word-oldcount;/*測(cè)得周期*/oldcount=newcount.word;one_round=1; /*每轉(zhuǎn)一圈,引起中斷,設(shè)置標(biāo)志*/}voidmain(void){IP=0x04; /*置INT1為高位優(yōu)先級(jí)*/TMOD=0x11; /*T0,T116位方式*/TCON=0x54; /*T0,T1運(yùn)行,IT1邊沿觸發(fā)*/第七十八頁(yè),共一百六十九頁(yè),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;}}}第七十九頁(yè),共一百六十九頁(yè),2022年,8月28日7.9.3串行口使用的C語(yǔ)言編程例6單片機(jī)fosc=11.0592MHz,波特率為9600,各設(shè)置32字節(jié)的隊(duì)列緩沖區(qū)用于發(fā)送接收。設(shè)計(jì)單片機(jī)和終端或另一計(jì)算機(jī)通信的程序。單片機(jī)串行口初始化成9600波特,中斷程序雙向處理字符,程序雙向緩沖字符。背景程序可以"放入"和"提取"在緩沖區(qū)的字符串,而實(shí)際傳入和傳出SBUF的動(dòng)作由中斷完成。Loadmsg函數(shù)加載緩沖數(shù)組,標(biāo)志發(fā)送開(kāi)始。緩沖區(qū)分發(fā)(t)和收(r)緩沖,緩沖區(qū)通過(guò)兩種指示(進(jìn)in和出out)和一些標(biāo)志(滿(mǎn)full,空empty,完成done)管理。隊(duì)列緩沖區(qū)32字節(jié)接收緩沖(r_buf)區(qū)滿(mǎn),不能再有字符插入。當(dāng)t_in=t_out,發(fā)送緩沖區(qū)(t_buf)空,發(fā)送中斷清除,停止UART請(qǐng)求。具體程序如下:第八十頁(yè),共一百六十九頁(yè),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;第八十一頁(yè),共一百六十九頁(yè),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;}}第八十二頁(yè),共一百六十九頁(yè),2022年,8月28日voidloadmsg(ucharcode*msg) /*item4*/{while((*msg!=0)&&((((t_in+1)^t_out)&0x1f)!=0)) /*測(cè)試緩沖區(qū)滿(mǎn)*/{t_buf[t_in]=*msg;msg++;t_in=++t_in&0x1f;if(t_done){TI=1;t_empty=t_done=0; /*完成重新開(kāi)始*/}}}第八十三頁(yè),共一百六十九頁(yè),2022年,8月28日voidprocess(ucharch){return;} /*item5*//*用戶(hù)定義*/voidprocessmsg(void) /*item6*/{while(((r_out+1)^r_in)!=0)/*接收非緩沖區(qū)*/{process(r_buf[r_out]);r_out=++r_out&0x1f;}}第八十四頁(yè),共一百六十九頁(yè),2022年,8月28日main() /*item7*/{TMOD=0x20; /*定時(shí)器1方式2*/TH1=0xfd; /*9600波特11.0592MHz*/TCON=0x40; /*啟動(dòng)定時(shí)器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();}}第八十五頁(yè),共一百六十九頁(yè),2022年,8月28日item1:背景程序"放入"和"提取"字符隊(duì)列緩沖區(qū)。item2:緩沖區(qū)狀態(tài)標(biāo)志。item3:串行口中斷服務(wù)程序,從RI,TI判別接收或發(fā)送中斷,由軟件清除。判別緩沖區(qū)狀態(tài)(滿(mǎn)full,空empty)和全部發(fā)送完成(done)。item4:此函數(shù)把字符串放入發(fā)送緩沖區(qū),準(zhǔn)備發(fā)送。item5:接受字符的處理程序,實(shí)際應(yīng)用自定義。item6:此函數(shù)逐一處理接收緩沖區(qū)的字符。item7:主程序即背景程序,進(jìn)行串行口的初始化,載入字符串,處理接收的字符串。第八十六頁(yè),共一百六十九頁(yè),2022年,8月28日7.10MCS-51片外擴(kuò)展的C語(yǔ)言編程7.10.18255與8031接口C應(yīng)用程序舉例

例78255控制打印機(jī)。圖7.7是8031擴(kuò)展8255與打印機(jī)接口的電路。8255的片選線(xiàn)為P0.7,打印機(jī)與8031采用查詢(xún)方式交換數(shù)據(jù)。打印機(jī)的狀態(tài)信號(hào)輸入給PC7,打印機(jī)忙時(shí)BUSY=1,微型打印機(jī)的數(shù)據(jù)輸入采用選通控制,當(dāng)STB上負(fù)跳變時(shí)數(shù)據(jù)被輸入。8255采用方式0由PC0模擬產(chǎn)生STB信號(hào)。按照接口電路,口A地址為7CH,口C地址為7EH,命令口地址為7FH,PC7~PC4輸入,PC3~PC0輸出。方式選擇命令字為8EH。第八十七頁(yè),共一百六十九頁(yè),2022年,8月28日?qǐng)D7.78031擴(kuò)展8255與打印機(jī)接口的電路第八十八頁(yè),共一百六十九頁(yè),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); /*查詢(xún)等待打印機(jī)的BUSY狀態(tài)*/第八十九頁(yè),共一百六十九頁(yè),2022年,8月28日PA8255=*p; /*輸出字符*/COM8255=0x00; /*模擬STB脈沖*/COM8255=0x01;p++;}}voidmain(void){ucharidataprn[]="WELCOME"; /*設(shè)測(cè)試用字符串*/COM8255=0x8e; /*輸出方式選擇命令*/toprn(prn); /*打印字符串*/}第九十頁(yè),共一百六十九頁(yè),2022年,8月28日例8EPROM編程器。由8031擴(kuò)展1片EPROM2716、2片SRAM6116及1片8255構(gòu)成EPROM編程器,編程對(duì)象是EPROM2732。擴(kuò)展編程系統(tǒng)中2716用來(lái)存放固化用監(jiān)控程序,用戶(hù)的待固化程序放在2片6116中。8255的口A作編程器數(shù)據(jù)口,口B輸出2732的低8位地址,PC3~PC0輸出2732高4位地址,PC7作2732啟動(dòng)保持控制器與PGM連接。譯碼地址為:6116(1):0800H;6116(2):1000H~17FFH;8255的口A:07FCH;口B:07FDH;口C:07FEH;命令口:07FFH。第九十一頁(yè),共一百六十九頁(yè),2022年,8月28日8255的口A、口B、口C均工作在方式0輸出,方式選擇命令字為80H;2732的啟動(dòng)編程和停止編程,由PC7的復(fù)位/置位控制,當(dāng)PC7=0時(shí)啟動(dòng)編程,PC7=1時(shí),編程無(wú)效。EPROM編程如下所示,參數(shù)為RAM起始地址、EPROM起始地址和編程字節(jié)數(shù)。#include<absacc.h>#include<reg51.h>#defineCOM8255XBYTE[0x07ff]#definePA8255XBYTE[0x07fc]#definePB8255XBYTE[0x07fd]#definePC8255XBYTE[0x07fe]#defineucharunsignedchar#defineuintunsignedint第九十二頁(yè),共一百六十九頁(yè),2022年,8月28日voidd1_ms(unitx);voidprogram(ram,eprom,con)ucharxdata*ram; /*RAM起始地址*/uinteprom,con; /*EPROM起始固化地址,固化長(zhǎng)度*/{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. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論