




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第8章單片機C語言應用程序設計18.1C語言與51單片機8.2C51數(shù)據(jù)類型及其在51單片機中的存儲方式8.3C51數(shù)據(jù)的存儲類型與51單片機存儲結構8.451單片機特殊功能寄存器的C51定義8.551單片機并行接口的C51定義8.6位變量的C51定義8.7C51的指針8.8與使用51單片機內部資源有關的頭文件8.951單片機內部資源應用的C語言編程8.1051單片機片外擴展的C語言編程8.11頻率、周期測量的C語言編程8.1251單片機間通信的C語言編程8.13鍵盤和數(shù)碼顯示人機交互的C語言編程在單片機應用系統(tǒng)開發(fā)中,應用程序設計是整個系統(tǒng)設計的主要工作,直接決定應用系統(tǒng)開發(fā)周期的長短。在過去,單片機應用程序設計都采用匯編語言。采用匯編語言編寫應用程序,可直接操縱系統(tǒng)的硬件資源,編寫出高質量的程序代碼。但是,采用匯編語言編寫比較復雜的數(shù)值計算程序非常困難,又因匯編語言源程序的可讀性遠不如高級語言源程序,若要修改一下程序的功能,得花費心思重頭閱讀程序。隨著計算機應用技術的發(fā)展,軟件開發(fā)工具日益豐富,出現(xiàn)了眾多支持高級語言編程的單片機開發(fā)工具。利用C語言設計單片機應用程序已經成為單片機應用系統(tǒng)開發(fā)設計的一種趨勢。使用C語言編程更符合人的思維方式和思考習慣,編寫代碼效率高、維護方便。采用C語言,易于開發(fā)復雜的單片機應用程序,有利于進行單片機產品的重新選型和應用程序的移植,大大提高了單片機應用程序的開發(fā)速度?,F(xiàn)在,單片機仿真器普遍支持C語言程序調試,為使用C語言進行單片機程序開發(fā)提供了便利的條件。世界上許多軟件公司都致力于51系列單片機高級語言編譯器的開發(fā)研究,給用戶采用高級語言編程提供了強有力的支持。本章從單片機應用特點的角度出發(fā),結合Keil公司的C51編譯器,介紹51單片機C語言應用程序開發(fā)設計的技術方法。8.1
C語言與51單片機8.1.1
51單片機C語言編程簡介
C語言是高級程序設計語言。用高級語言編程時,不必太多考慮計算機的硬件特性和接口結構。事實上,任何高級語言程序最終必須要轉換成計算機可識別、并能執(zhí)行的機器指令代碼,定位于存儲器。程序中的數(shù)據(jù)也必須以一定的存儲結構定位于存儲器中。這種轉換、定位是由高級語言編譯器來實現(xiàn)的。在高級語言程序中,對不同類型數(shù)據(jù)的存儲及引用是通過不同類型的變量來實現(xiàn)的。也可以說,高級語言的變量就代表存儲單元,變量的類型結構就表示了數(shù)據(jù)的存儲、引用結構。用匯編語言設計51單片機應用程序時,必須考慮存儲器結構,尤其要考慮其片內數(shù)據(jù)存儲器與特殊功能寄存器的正確、合理使用以及按實際地址處理端口數(shù)據(jù)。盡管采用C語言編寫51單片機應用程序時,不像用匯編語言那樣具體地組織、分配存儲器資源和處理端口數(shù)據(jù),甚至可以在對單片機內部結構和存儲器結構不太熟悉、對處理器的指令集沒有深入了解的情況下編寫應用程序,但要使編譯器產生充分利用單片機資源、執(zhí)行效率高、適合51單片機目標硬件的程序代碼,對數(shù)據(jù)類型和變量的定義就必須與單片機的存儲結構相關聯(lián),否則編譯器就不能正確地映射定位。
同時,在C語言編程中,必須注意到單片機內部資源的寶貴性和控制實時性的應用特點,考慮產生的可執(zhí)行代碼運行時所占用的系統(tǒng)資源。因此,使用C語言編寫單片機應用程序和編寫標準的C語言程序的主要不同之處就在于它是根據(jù)單片機存儲結構及內部資源定義相應的C語言數(shù)據(jù)和變量,而其他的語法規(guī)定、程序結構及程序設計方法都與標準的C語言程序相似。從這個角度來說,沒有對單片機硬件資源、體系結構和指令系統(tǒng)的充分了解,就不能設計出非常實用、高質量的單片機應用程序。用C語言編寫的應用程序必須經過單片機C語言編譯器(簡稱C51)轉換成51單片機可執(zhí)行的代碼程序。所以,C語言編譯器是C語言應用程序開發(fā)設計中必不可少的開發(fā)工具,C語言編譯器的好壞直接影響到生成代碼的效率、大小和可靠性。8.1.2
C51開發(fā)工具與單片機C語言編譯器下面對一些主要工具作簡要說明。
μVision項目管理器和編輯器:一個集成開發(fā)環(huán)境,它將項目管理、源代碼編輯、連接和程序調試等組合在一個功能強大的環(huán)境中。
C51國際標準優(yōu)化C交叉編譯器:從C源代碼產生可重定位的目標模塊。
A51宏匯編器:從8051匯編源代碼產生目標模塊。
BL51連接器/定位器:組合由C51和A51產生的可重定位的目標模塊,生成絕對目標模塊。
LIB51庫管理器:從目標模塊生成連接器可以使用的庫文件。
OH51Object-HEX轉換器:從絕對目標模塊生成IntelHEX文件。
RTX51實時操作系統(tǒng):簡化了復雜的實時應用軟件項目的設計。上述工具是為專業(yè)軟件開發(fā)者設計的,但任何水平的編程者都可使用。Keil軟件公司將這些工具都集合在一個套件內。為滿足不同用戶需求,將軟件開發(fā)工具進行綁定,形成了不同的開發(fā)套件或工具包。
PK51專業(yè)開發(fā)套件:該套件提供了所有工具,適合為專業(yè)開發(fā)人員建立和調試51系列單片機的復雜嵌入式應用。專業(yè)開發(fā)套件可針對具體的51系列單片機產品進行配置使用。
DK51開發(fā)套件:該套件是PK51的精簡版,不包括RTX51Tiny實時操作系統(tǒng)。開發(fā)套件可針對8051及其所有派生產品進行配置使用。
CA51編譯器套件:該套件是只需要C編譯器而不需要調試系統(tǒng)的開發(fā)者的最佳選擇,只包含μVisionIDE集成開發(fā)環(huán)境,不提供μVision調試器的功能。這個套件包括了要建立嵌入式應用的所有工具軟件,可針對8051及其所有派生產品進行配置使用。
A51匯編器套件:該套件包括一個匯編器和所有創(chuàng)建嵌入式應用的工具。它可針對8051及其所有派生產品進行配置使用。
RTX51實時操作系統(tǒng)(RF51):該系統(tǒng)是一個用于51系列單片機的實時內核程序。RTX51Full實時內核提供RTX51Tiny的所有功能和一些擴展功能,并且包括CAN通信協(xié)議接口子程序。8.1.3
Keil80C51開發(fā)工具
C51的特色主要體現(xiàn)在以下幾個方面:
(1)?C51雖然繼承了標準C語言的絕大部分特征,而且基本用法相同,但它針對51系列單片機特定的硬件結構有所擴展,如數(shù)據(jù)類型、存儲模式、端口操作等。
(2)?C51的使用必須注重對51系列單片機系統(tǒng)資源的理解和掌握,因為相對于通用微型計算機,單片機的系統(tǒng)資源非常有限,開發(fā)人員對單片機的程序存儲器、數(shù)據(jù)存儲器等要充分、合理利用。
(3)要考慮應用程序的代碼質量,不要對系統(tǒng)造成過重的負擔,如代碼優(yōu)化等問題。
KeilC51編譯器是符合ANSI標準的C編譯器。KeilC51語言擴展支持51單片機的應用包括:數(shù)據(jù)類型,存儲器類型,存儲器模型,指針,載入函數(shù),中斷函數(shù),實時操作系統(tǒng),PL/M和A51源文件接口。本章將介紹其中的主要擴展功能。
8.2C51數(shù)據(jù)類型及其在51單片機中的存儲方式
8.2.1KeilC51中的基本數(shù)據(jù)類型
KeilC51支持的基本數(shù)據(jù)類型有位型(bit)、無符號字符型(unsignedchar)、有符號字符型(signedchar)、無符號整型(unsignedint)、有符號整型(signedint)、無符號長整型(unsignedlong)、有符號長整型(signedlong)和浮點型(float)等。
KeilC51具體支持的基本數(shù)據(jù)類型及其長度、數(shù)域如表8.1所示。除了這些類型外,還可以將基本類型組合成復雜數(shù)據(jù)結構。通過表8.1可以看出:
(1)?C51具有標準C語言的標準數(shù)據(jù)類型。另外,為了充分利用51單片機的硬件結構,還擴充了位變量(bit)、可尋址位(sbit)、特殊功能寄存器(sfr)和16位特殊功能寄存器(sfr16)數(shù)據(jù)類型。
(2)由于51單片機是8位機,因而不存在字節(jié)校準問題,這意味著數(shù)據(jù)結構成員是順序放置的。擴充的數(shù)據(jù)類型位變量(bit)、可尋址位(sbit)、特殊功能寄存器(sfr)和16位特殊功能寄存器(sfr16)專門用于51系列單片機硬件和C51編譯器,并不是ANSIC的一部分,不能通過指針進行訪問。bit、sbit、sfr和sfr16數(shù)據(jù)類型可用于訪問51單片機的特殊功能寄存器。
當在一個處理中遇到不同數(shù)據(jù)類型時,C51編譯器自動轉換數(shù)據(jù)類型。例如,將一個位變量賦給一個整型變量時,位型值自動轉換為整型值。有符號變量的符號也能自動進行處理。這些轉換也可以用C語言的標準指令進行人工轉換。8.2.2C51數(shù)據(jù)在51單片機中的存儲方式
雖然KeilC51支持表8.1列出的所有數(shù)據(jù)類型,但在51單片機中,只有bit和unsignedchar兩種直接支持機器指令。在C語言程序中使用其他數(shù)據(jù)類型,C51編譯器要調用一系列庫函數(shù)對其進行復雜的數(shù)據(jù)類型處理。特別是當使用浮點變量時,將明顯地增加運算時間和程序的長度。如果在編寫單片機C程序時,不考慮單片機數(shù)據(jù)處理的特點,無約束地使用大量的、不必要的變量類型,則將導致C51編譯器相應地增加所調用庫函數(shù)的數(shù)量,以處理大量增加的變量類型,最終會使程序變得過于龐大,造成存儲器資源浪費,運行速度減慢,甚至會在連接(link)時出現(xiàn)因程序過大而裝不進代碼區(qū)的情況。所以,必須特別慎重地進行變量和數(shù)據(jù)類型的選擇。
C程序中不同的類型數(shù)據(jù),最終在單片機中以不同的方式進行存儲。下面說明表8.1所列數(shù)據(jù)類型在51系列單片機中的存儲方式。
位變量(bit):與51單片機硬件特性操作有關的位可以定義為位變量。位變量必須定位在51單片機的片內RAM的位尋址空間中。字符變量(char):字符變量的長度為1字節(jié),正好存儲在51單片機的一個數(shù)據(jù)單元中。對于無符號字符變量類型(unsignedchar)的數(shù)據(jù),其字節(jié)中的所有位均用來表示數(shù)據(jù)的數(shù)值,它的值域范圍是0~255。對于有符號字符變量(signedchar),最具有重要意義的是最高位上的符號標志位(msb),此位為0代表“正”,為1代表“負”。負數(shù)一般用補碼表示,例如11111111表示-1。當進行乘除法運算時,符號問題就變得十分復雜,C51編譯器會自動地將相應的庫函數(shù)調入程序中來解決這個問題。整型變量(int):整型變量長度為16位,在51系列單片機占用2個字節(jié)存儲,數(shù)據(jù)的高位字節(jié)存放在低地址字節(jié)中,低位字節(jié)數(shù)放在高地址字節(jié)中。這與通用微機系統(tǒng)中的存儲結構是不同的。有符號整型變量(signedint)也使用最高位作符號位,并使用二進制補碼表示數(shù)值。例如:整型變量值0x1234以圖8.1所示的方式存儲。
長整型變量(longint):長整型變量長度為32位,在51系列單片機中按照由高位到低位的順序連續(xù)占用4個字節(jié)存儲。例如:長整型變量值0x12345678以圖8.2所示的方式存儲。圖8.1整型變量的存儲結構圖8.2長整型變量的存儲結構浮點型變量(float):浮點型變量為32位二進制數(shù),占4
個字節(jié)。它用符號位表示數(shù)的符號,用階碼和尾數(shù)表示數(shù)
的大小。
用它們進行任何數(shù)學運算都需要使用由編譯器決定的
各種不同效率等級的庫函數(shù)。KeilC51的浮點型數(shù)據(jù)是IEEE-754標準的單精度浮點型數(shù)據(jù),在十進制中具有7位有效數(shù)字。
浮點型變量在內存中的存放格式如下:其中,S為符號位,“0”表示正,“1”表示負。E為階碼,占用8位二進制數(shù),存放在兩個字節(jié)中。階碼E是以2為底的指數(shù)再加上127,這樣避免了出現(xiàn)負的階碼值,而指數(shù)是可正可負的。階碼E的正常取值范圍是1~254,從而實際指數(shù)的取值范圍是?-126~127。M為尾數(shù)的小數(shù)部分,用23位二進制數(shù)表示,存放在3個字節(jié)中。尾數(shù)的整數(shù)部分總為1,因此不用保存,它是隱含存在的。小數(shù)點位于隱含的整數(shù)位“1”的后面。一個浮點數(shù)的數(shù)值范圍是(-1)S×2E-127×(1.M)。例如,浮點數(shù)-12.5的存儲碼為0xC1480000,
(-12.5)10=(-1100.1)2=(-1.1001×23)
即S=1,EEEEEEEE=(127+3)10=(1111111+11)2=10000010
在存儲器中的存儲格式如下:值得注意的是,浮點型數(shù)據(jù)除了有正常數(shù)值之外,還可能出現(xiàn)非正常數(shù)值。根據(jù)IEEE標準,當浮點型數(shù)據(jù)取以下數(shù)值(十六進制數(shù))時,即為非正常值:
0xFFFFFFFNaN(非正常數(shù))
0x7F80000+INF(正無窮大)
0xFF80000-INF(負無窮大)由于51單片機不包括捕獲浮點運算錯誤的中斷向量,因此用戶必須根據(jù)可能出現(xiàn)的錯誤條件,用軟件來進行適當?shù)奶幚?。下面就有符?無符號(signed/unsigned)問題做一些說明。在編寫程序時,如果使用signed和unsigned兩種數(shù)據(jù)類型,那么就得使用兩種格式類型的庫函數(shù),這將使占用的存儲空間成倍增長。因此,如果只強調程序的運算速度而不進行負數(shù)運算,則最好采用無符號(unsigned)格式。無符號字符類型的使用:無論何時,應盡可能地使用無符號變量,因為它能直接被51單片機所接受?;谕瑯拥脑?也應盡可能使用位變量。有符號字符變量雖然也只占用1個字節(jié),但需要進行額外的操作來測試代碼的符號位,這無疑會降低代碼的效率。最后要提到的是使用縮寫形式定義數(shù)據(jù)類型。在編程時,為了書寫方便,經常使用簡化的縮寫形式來定義變量的數(shù)據(jù)類型。其方法是在源程序開頭使用#define語句。例如:
#defineucharunsignedchar
#defineuintunsignedint這樣,在以后的程序中,就可以用uchar代替unsignedchar,用uint代替unsignedint來定義變量。8.3
C51數(shù)據(jù)的存儲類型與
51單片機存儲結構8.3.1存儲類型
51單片機中,程序存儲器與數(shù)據(jù)存儲器嚴格分開,數(shù)據(jù)存儲器又分為片內、片外兩個獨立的尋址空間,特殊功能寄存器包含在片內RAM空間,但不能用于存儲用戶數(shù)據(jù),這是51單片機與一般微機存儲器結構有所不同的顯著特點。
KeilC51完全支持51單片機的硬件結構,提供了對所有存儲區(qū)的訪問機制。在C程序中定義數(shù)據(jù)對象(變量、常量等)時,通過聲明存儲類型,將它們準確定位在不同的存儲區(qū)中。
C51中定義變量的一般格式如下:數(shù)據(jù)類型存儲類型變量名
C51存儲類型與51單片機存儲區(qū)的對應關系如表8.2所示。
C51存儲類型既確定數(shù)據(jù)對象的存儲區(qū),同時也限定了數(shù)據(jù)長度。存儲類型與存儲長度的限定關系如表8.3所示。下面舉例說明C51存儲類型。
(1)code:當使用code存儲類型定義數(shù)據(jù)時,C51編譯器會將其定位在程序存儲器空間,對code區(qū)的訪問和對xdata區(qū)的訪問時間是一樣的。程序存儲器空間的對象在編譯的時候初始化。下面是code存儲類型聲明的例子:
unsignedcharcodetab[16]={
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15
};
charcodetext[]=“enterpassword”;
(2)?data:使用data存儲類型定義數(shù)據(jù)時,C51編譯器會將其定位在片內直接尋址的存儲器空間。定義data存儲類型時需注意以下兩點:
片內RAM存儲區(qū)能快速存取數(shù)據(jù),但容量非常有限,所以臨時性數(shù)據(jù)和頻繁使用的數(shù)據(jù)應選擇data存儲類型。
片內RAM存儲區(qū)中除了包含程序變量外,還包含了堆棧和寄存器組。在定義data存儲類型變量的數(shù)量時,應同時考慮寄存器組和堆棧的使用情況。C51使用默認的寄存器來傳遞參數(shù)。另外,還需定義足夠大的堆棧空間,當內部堆棧溢出的時候,程序可能會出現(xiàn)看似莫名其妙的復位,其原因是51系列單片機中沒有硬件報錯機制,堆棧溢出以這種方式表示出來。下面是幾個data存儲類型聲明的例子:
unsignedchardatasystem_status=0;
unsignedintdataunit_id[8];
chardatainp_str[16];
(3)bdata:使用bdata存儲類型定義數(shù)據(jù)時,C51編譯器將其定位在片內存儲器空間的位尋址區(qū)。編譯器不允許在bdata段中定義float和double類型的變量。定義之后,這個變量就可進行位尋址。存儲狀態(tài)信息是十分有用的,因為它可以單獨地使用變量的每一位,有關位變量的定義和引用的例子詳見8.6節(jié)。
(4)idata:idata存儲類型對應間接尋址的片內全部數(shù)據(jù)存儲空間(256B),idata區(qū)也可存放使用比較頻繁的變量和臨時性數(shù)據(jù)。使用寄存器作為指針進行尋址,在寄存器中設置8位地址進行間接尋址。與外部存儲器尋址相比,它生成的指令執(zhí)行周期和代碼長度都比較短。下面是幾個idata存儲類型聲明的例子:
unsignedcharidatasystem_status=0;
unsignedintidataunit_id[8];
charidatainp_str[16];
(5)pdata和xdata:當使用xdata存儲類型定義常量和變量時,C51編譯器會將其定位在片外數(shù)據(jù)存儲器空間,該空間的最大尋址范圍為64KB。片外數(shù)據(jù)存儲器主要用于存放不常使用的變量值、待處理的數(shù)據(jù)或準備發(fā)往另一臺計算機的數(shù)據(jù)。在使用外部數(shù)據(jù)存儲器空間中的數(shù)據(jù)時,必須用指令將它們全部傳送到單片機片內數(shù)據(jù)存儲空間,數(shù)據(jù)處理完后,再將結果返回到外部數(shù)據(jù)存儲器中。
pdata存儲類型屬于xdata類型,但它可用工作寄存器R0或R1間接分頁訪問,即由R0或R1提供8位的頁內地址,其高8位地址(頁面地址)被妥善保存在P2口中,多用于I/O操作。因為對pdata尋址只需要裝入8位地址,而對xdata尋址需裝入16位地址,所以對pdata尋址比對xdata尋址要快,應盡量把外部數(shù)據(jù)存儲在pdata區(qū)中。下面是一個定義pdata和xdata存儲類型變量的例子:
include〈reg51.h〉
unisgnedcharpdatainp_reg1;
unsignedcharxdatainp_reg2;
voidmain(void)
{
inp_reg1=P1;
inp_reg2=P3;
}8.3.2存儲模式定義變量時,如果缺省存儲器類型,則按編譯時使用的存儲器模式來規(guī)定默認的存儲類型,確定變量的存儲空間。存儲模式決定無明確存儲類型說明的變量的存儲類型和參數(shù)傳遞區(qū)。下面說明三種存儲器模式對變量的影響。
C51中有三種存儲模式。
(1)?SMALL模式。在此模式下,默認的存儲類型為data,參數(shù)及局部變量定位于直接尋址的片內數(shù)據(jù)存儲區(qū)(最大128B),對變量訪問的速度快,但空間很有限,只適用于小程序。
(2)?COMPACT模式。在此模式下,默認的存儲類型為pdata,參數(shù)及局部變量定位于分頁片外部數(shù)據(jù)存儲區(qū),通過@R0或@R1間接尋址。對變量訪問的速度要比SMALL模式慢一些。
(3)?LARGE模式。在此模式下,默認的存儲類型為xdata,參數(shù)及局部變量定位于片外部數(shù)據(jù)存儲區(qū),使用數(shù)據(jù)指針寄存器DPTR間接尋址,存儲空間大,可存儲變量多,但訪問速度慢。8.4
51單片機特殊功能寄存器的C51定義
51系列單片機中,除了程序計數(shù)器PC和4組通用工作寄存器之外,其他所有的寄存器均為特殊功能寄存器(SFR)。對于經典的51單片機,SFR分散在片內RAM區(qū)的高128字節(jié),地址范圍是0x80~0xFF;對于Philips80C51MX單片機,SFR的地址范圍是0x180~0x1FF。51單片機的有些寄存器具有位尋址能力,它們的字節(jié)地址都能被8整除,即字節(jié)地址以0或8為尾數(shù)。
為了訪問51單片機中特殊功能寄存器,C51提供了sfr、sfr16和sbit關鍵字,用來定義8位、16位特殊功能寄存器和可獨立尋址的位。這幾個關鍵字與標準C語言不兼容,只適用于51系列單片機的C語言編程。8位特殊功能寄存器的一般方法如下:sfrsfr_name=int_constant;其中:“sfr_name”是一個真實存在的特殊功能寄存器名;“int_constant”是被定義的特殊功能寄存器的字節(jié)地址,只能用整型常數(shù)表示。如此定義后,就建立起寄存器名稱符號與地址的關聯(lián),在程序中就可使用被定義的名稱符號來訪問真實地址的特殊功能寄存器了。例如:sfrP0=0x80;/*定義P0口*/
sfrPSW=0xD0;/*定義標志寄存器*/
sfrTMOD=0x89;/*定義定時器/計數(shù)器方式控制寄存器*/
sfrTH0=0x8C;/*定義定時器/計數(shù)器0高字節(jié)*/
sfrTL0=0x8A;/*定義定時器/計數(shù)器0低字節(jié)*/在新的51系列產品中,增加了一些可按16位訪問的特殊功能寄存器,其高字節(jié)地址直接位于其低字節(jié)之后時,例如AT89C52單片機的定時器/計數(shù)器T2就是這種情況。對于這類特殊功能寄存器,可使用關鍵字“sfr16”來定義,其定義語句的語法格式與8位SFR相同,只是“=”后面必須用低字節(jié)地址,即以低字節(jié)地址作為“sfr16”的定義地址。
例如:
sfr16T2=0xCC;
/*定時器/計數(shù)器T2L地址為CCH,T2H地址為CDH*/這種定義適用于所有新的16位SFR,但不能用于定時器/計數(shù)器C/T0和C/T1。
對于特殊功能寄存器中可獨立尋址的位,可使用關鍵字“sbit”來定義。其定義的一般格式為:
sbitbit_name=bit_adress
“bit_name”是被定義的位單元的名稱符號,“bit_adress”是位單元地址。在51單片機中位單元地址可用“可位尋址的特殊寄存器名稱·位序號”、“可位尋址的字節(jié)地址·位序號”和“直接位地址”三種方式來表示。在C51中也有三種位單元的定義格式。第一種格式:sbitbit_name=sfr_name^int_constant
其中,位地址用已經定義過可位尋址的特殊功能寄存器的名稱符號和位序號來表示。例如:
sfrPSW=0xD0; /*定義標志寄存器*/
sbitOV=PSW^2; /*定義OV表示PSW的第2位*/
sbitCY=PSW^7; /*定義CY表示PSW的第7位*/
第二種格式:sbitbit_name=int_constant^int_constant其中,位地址用可位尋址字節(jié)地址和位序號來表示。例如:
sbitOV=0xD0^2;/*定義OV表示PSW的第2位*/
sbitCY=0xD0^7;/*定義CY表示PSW的第7位*/
第三種格式:sbitbit_name=int_constant
其中,“int_constant”為絕對位地址位。例如:
sbitOV=0xD2; /*定義OV表示絕對地址為D2H的位*/
sbitCY=0xD7; /*定義OV表示絕對地址為0D7H的位*/由于在51系列單片機產品中特殊功能寄存器的數(shù)量與類型不盡相同,因此建議將所有特殊功能寄存器的“sfr”定義放入一個頭文件中。該文件應包括51單片機機型中的特殊功能寄存器的定義。C51編譯器的“reg51.h”就是定義51單片機中的特殊功能寄存器的頭文件。在程序開頭,只要有“#inlcluedreg51.h”,就可用單片機中的特殊功能寄存器名稱、位符號名稱來訪問其數(shù)據(jù)。8.5
51單片機并行接口的C51定義
51系列單片機并行I/O口除了芯片上的4個并行I/O口(P0~P3)外,還可以在片外擴展并行I/O口。51系列單片機I/O口與數(shù)據(jù)存儲器統(tǒng)一編址,即把一個I/O口當作數(shù)據(jù)存儲器中的一個單元來看待。使用C51編程時,51單片機片內的I/O口與片外擴展的I/O口可以統(tǒng)一在一個頭文件中定義,也可以在程序中(一般在開始的位置)定義。對于51單片機片內的I/O口按特殊功能寄存器方法定義,其定義方法舉例如下:sfrP0=0x80;/*定義端口0,地址為80H*/sfrP1=0x90;/*定義端口1,地址為90H*/對于片外擴展I/O口,則根據(jù)硬件譯碼地址,將其視做片外數(shù)據(jù)存儲器的一個單元,使用#include語句進行定義。例如:#include<absacc.h>/*將PRTOUT定義為外部I/O口,地址為0xFFC0, 長度為8位*/#definePRTOUTXBYTE[0xFFC0]PRTOUT=0x80;/*由已定義端口PRTOUT輸出數(shù)據(jù)0x80*/例子中的absacc.h是C51中絕對地址訪問函數(shù)的頭文件,XBYTE是C51提供的用于絕對地址定位的宏。采用以上方法尋址是通過包含絕對地址訪問頭文件absacc.h實現(xiàn)的。用戶可以充分利用C51運行庫提供的預定義宏來進行任意地址的直接操作。例如,可以這樣定義一個D/A轉換接口的地址,每向該地址寫入一個數(shù)據(jù)即可啟動一次D/A轉換:#include<absacc.h>#defineDAC0832XBYTE[0x7FFF]/*定義DAC0832端 口地址*/DAC0832=0x80; /*啟動一次D/A轉換*/另一個經常定義外部I/O口的方法是使用C51的擴展關鍵字“_at_”,用“_at_”給I/O器件指定變量名非常簡單。例如,在XDATA區(qū)的地址0xFFC0處有一個8位的擴展輸入口,可以這樣為它指定變量名:
unsignedcharxdatainPRT_at_0xFFC0;在頭文件或程序中對這些片內外I/O口定義后,在程序中就可以利用變量名與其實際地址之間的聯(lián)系,用軟件模擬51單片機的硬件操作。8.6位變量的C51定義除了通常的C數(shù)據(jù)類型外,C51編譯器還支持“bit”數(shù)據(jù)類型,這對于記錄系統(tǒng)狀態(tài)是十分有用的,因為它往往需要使用某一位而不是整個數(shù)據(jù)字節(jié)。8.6.1位變量的C51定義在使用C51編程時,定義了位變量后,就可以用定義的變量來表示51單片機的位尋址單元。在C51中定義位變量的一般語法形式如下:位類型標識符(bit)位變量名;
bitmy_bit; /*把my_bit定義為位變量*/
bitdirection_bit; /*把direction_bit定義為位變量*/函數(shù)參數(shù)列表中可以包含類型為“bit”的參數(shù),也可使用bit類型的返回值。例如:
bitdone_flag=0;
/*把done_flag定義為位變量*/
bittestfunc(bitflag1,bitflag2)
{ /*flag1和flag2為bit類型的參數(shù)*/
return(flag); /*flag是bit類型的返回值*/
}8.6.2對位變量定義的限制
(1)位變量不能定義成一個指針,原因是不能通過指針訪問“bit”類型的數(shù)據(jù),如定義“bit*ptr;”是非法的。
(2)不存在位數(shù)組,如不能定義bitSHOW_BUF[6]。
(3)值得注意的是,使用中斷禁止(#pragmadisable)或包含明確的寄存器組切換(usingn)的函數(shù)不能返回位值,否則編譯器會給出一個錯誤信息。在位定義中,允許定義存儲類型,位變量都被放入一個位段,此位段總位于51單片機片內的RAM中,因此存儲器類型限制為data和idata。如果把位變量的存儲類型定義為其他存儲類型,將導致編譯出錯??梢韵榷x變量的數(shù)據(jù)類型和存儲類型,然后使用“sbit”定義可尋址訪問的位對象。例如:intbdataibase; /*定義ibase為bdata整型變量*/charbdatabary[4];/*定義bary[4]為bdata字符型數(shù)組*/sbitmybit0=ibase^0;/*定義mybit0為ibase的第0位*/sbitmybit15=ibase^15;/*定義mybit15為ibase的第15位*/sbitAry07=bary[0]^7;/*定義Ary07為bary[0]的第7位*/sbitAry37=bary[3]^7;/*定義Ary37為bary[3]的第7位 */對ibase和bary也可以字節(jié)尋址:
Ary37=0; /*bary[3]的第7位清零*/
bary[3]=′a′;/*字節(jié)尋址,bary[3]賦值為′a′*/
mybit15=1; /*ibase的第15位置1*/用sbit定義時,要求尋址對象所在字節(jié)基址對象的存儲類型為“bdata”,否則只有絕對的特殊位定義(sbit)是合法的。操作符后的最大值依賴于指定的基類型,對于char和
unsignedchar而言是0~7,對于int、unsignedint、short和unsignedshort而言是0~15,對于long和unsignedlong而言是0~31。比如,在BDATA段中聲明變量和使用位變量:
unsignedcharbdatastatus_byte;
unsignedintbdatastatus_word;
unsignedlongbdatastatus_dword;
sbitstat_flag=status_byte^4;
if(status_word^15){
…}
stat_flag=1;8.7
C51的指針前面講述的字符型(char)、整型(int)、浮點型(float)、位型(bit)等數(shù)據(jù),都屬于C51的基本數(shù)據(jù)類型。C語言還提供了一些擴展的數(shù)據(jù)類型,它們是由基本數(shù)據(jù)類型按一定的規(guī)則組合而成的數(shù)據(jù)類型,稱之為構造數(shù)據(jù)類型。構造數(shù)據(jù)類型有數(shù)組、結構、指針、共用體、枚舉等。
C51支持的構造數(shù)據(jù)類型的數(shù)目與標準C語言一樣,對構造類型定義、引用及其運算的規(guī)則也同標準C語言基本一樣,只是定義構造類型時,可由C51支持的基本數(shù)據(jù)類型組合而成。在這里需要一提的是:標準C語言中,定義構造數(shù)據(jù)類型時,不太去考慮存儲空間問題,而使用C51編寫單片機應用程序時,就需要比較慎重地考慮存儲空間問題,因為經典的51單片機的最大數(shù)據(jù)存儲空間只有64KB。如果隨意定義太大規(guī)模的構造類型數(shù)據(jù),就會浪費大量的存儲空間,使構造類型的數(shù)據(jù)元素不能被有效地利用。因此在進行C51編程開發(fā)時,要根據(jù)需要來選擇構造類型數(shù)據(jù)的大小。下面對KEILC51的指針類型進行詳細說明。C51編譯器支持使用“*”符號說明的指針,可以使用指針執(zhí)行標準C中所有可執(zhí)行的操作。針對8051及其派生器件的獨特結構,C51支持兩種不同類型的指針:通用指針和指定存儲器的指針。8.7.1通用指針與指定存儲器的指針
C51中指針區(qū)分為通用指針和指定存儲器的指針,兩種指針的定義和使用是有區(qū)別的。
1.指針定義
C51中定義指針的一般形式為數(shù)據(jù)類型[存儲器類型1]*[存儲器類型2]指針變量名;數(shù)據(jù)類型:表示指針變量所指向數(shù)據(jù)的類型。存儲器類型1:表示指針變量所指向數(shù)據(jù)的存儲空間。如果不定義該選項,就定義為通用指針。如果定義了該選項,就定義為指定存儲器的指針。存儲類型2:表示指針變量本身的存儲空間。如果不定義該選項,指針變量的值(指針)被默認存放在data區(qū)(片內RAM區(qū))。如果定義了該選項,指針變量的值被存放在指定的存儲區(qū)。*?和指針變量名的意義與標準C語言完全一樣。
2.通用指針與指定存儲器指針的區(qū)別
通用指針和指定存儲器的指針不僅在定義形式上有區(qū)別,而且在使用上也有區(qū)別。主要區(qū)別有以下三點。
(1)對指針的存儲不同。通用指針存儲占用三個字節(jié),第一個字節(jié)存放該指針存儲器類型的編碼(編譯時由編譯模式的默認值確定),第二和第三字節(jié)分別存放該指針的高8位和低8位地址。存儲器類型的編碼值如表8.4所示。表8.4存儲器類型的編碼值指定存儲器的指針在定義中指定了指針所指數(shù)據(jù)的存儲區(qū),編譯時不用識別存儲器類型(不需存儲存儲器類型碼),只占用一個或二個字節(jié)存放指針,idata、data、pdata存儲器指針占一個字節(jié),code、xdata占二個字節(jié)。
(2)通用指針可以訪問存儲器空間任何位置的數(shù)據(jù),指定存儲器的指針只能訪問指定存儲區(qū)的數(shù)據(jù)。使用通用指針,可以不考慮數(shù)據(jù)在存儲器中的位置,因此許多庫程序使用這種類型的指針。
(3)通用指針產生的代碼比指定存儲器指針產生代碼的執(zhí)行速度要慢。因為存儲區(qū)在編譯前是未知的,編譯器不能優(yōu)化存儲區(qū)訪問,而必須產生可以訪問存儲區(qū)的通用代碼。
3.定義指針舉例
(1)
char*c_ptr;
int*i_ptr;
long*l_ptr;
定義了三個通用指針,c_ptr指向的是一個字符型變量,i_ptr指向的是一個整型變量,l_ptr指向的是一個長整變量,三個指針變量本身存放于片內數(shù)據(jù)存儲區(qū)。指針所指向的數(shù)據(jù)位于哪里,與編譯時編譯模式的設置有關:
如果模式為Large,則數(shù)據(jù)位于xdata區(qū);
如果模式為Compact,則數(shù)據(jù)位于pdata區(qū);
如果模式為Small,則數(shù)據(jù)位于data區(qū)。
(2)char*datac_ptr;
int*idatai_ptr;
long*xdatal_ptr;
定義了三個通用指針,指定c_ptr、i_ptr、l_ptr變量本身分別存于data、idata、xdata區(qū)。
(3)
Chardata*datac_ptr;
intxdata*idatai_ptr;
longcode*xdatal_ptr;
定義了三個指定存儲器的指針,且指定了c_ptr、i_ptr、l_ptr變量本身分別存于data、idata、xdata區(qū)。c_ptr指向的是data區(qū)中的字符型變量,i_ptr指向的是xdata區(qū)中的整型變量,l_ptr指向的是code區(qū)中的長整型變量。8.7.2指針轉換
C51編譯器可以在指定存儲器指針和通用指針之間轉換,指針轉換可以用類型轉換的程序代碼來強迫轉換,或在編譯器內部強制轉換。
有些函數(shù)調用中,進行參數(shù)傳遞時需要采用一般指針,像C51的庫函數(shù)、printf、sprintf、gets等函數(shù)要求使用一般指針作為參數(shù)。當把指定存儲區(qū)的指針作為參數(shù)傳遞給要求使用通用指針的函數(shù)時,C51編譯器就把指定存儲區(qū)指針轉換為一般指針。指定存儲區(qū)的指針作為參數(shù)時,如果沒有函數(shù)原型,就經常被轉換為一般指針。如果被調用函數(shù)的參數(shù)為某種較短長度指針,則會產生程序錯誤。為避免此類錯誤,應該采用預處理命令將函數(shù)的說明文件包含到C語言源程序中。
通用指針到指定存儲器指針的轉換規(guī)則如表8.5所示。指定存儲器指針到通用指針的轉換規(guī)則如表8.6所示。8.8與使用51單片機內部資源有關的頭文件
KeilC51提供了豐富的庫函數(shù),為使用戶能方便地使用,將庫函數(shù)分類,按類提供一個擴展名為“h”的頭文件。在頭文件中定義一類函數(shù)的公用變量、函數(shù)原型,或是定義一種功能的宏。用戶在使用C51提供的某一類函數(shù)或某一種功能時,只要用“#include”命令將對應的頭文件包含到自己的程序文件中,即可直接使用。KeilC51提供的頭文件在“\\Keil\C51\INC”目錄下,其中大多數(shù)頭文件的功能、作用及其使用基本與標準C相同。下面主要介紹幾個與使用51單片機內部資源有關的頭文件。
1.reg51.h/reg52.h
reg51.h是定義51子系列單片機全部特殊功能寄存器及其可獨立尋址位的頭文件。例如:
sfrP0=0x80;
sfrPSW=0xD0;
sfrTMOD=0x89;
sbitRS0=0xD3;
sbitRS1=0xD4;
sbitEA=0xAF;經reg51.h中的定義,就建立了特殊功能寄存器/可獨立尋址位與其地址的對應關系,且使用了單片機中真實的名稱符號。只要在程序文件中使用“include<reg51.h>”,在C程序中就可直接使用51單片機中的真實特殊功能寄存器或位的名稱符號,對其進行操作。
reg52.h是定義52子系列單片機全部特殊功能寄存器/可獨立尋址位的頭文件。
2.absacc.h
absacc.h是直接訪問51單片機各存儲空間數(shù)據(jù)及函數(shù)的宏定義頭文件。例如:
#defineDBYTE((unsignedcharvolatiledata*)0)
這個宏定義了DBYTE是指向片內直接尋址數(shù)據(jù)存儲器空間(128B)無符號字符型數(shù)據(jù)的指針,與數(shù)據(jù)段初始偏移量為0,即為一個空指針。
在absacc.h中,按照同樣的宏結構還定義了CBYTE、PBYTE、XBYTE、CWORD、DWORD、PWORD、XWORD,指向不同存儲空間及不同數(shù)據(jù)類型的指針。
CBYTE是指向程序存儲器空間中無符號字符型數(shù)據(jù)的空指針。PBYTE是指向片外數(shù)據(jù)存儲器分頁訪問空間(256B)中無符號字符型數(shù)據(jù)的空指針。
XBYTE是指向片外數(shù)據(jù)存儲器空間(64KB)中無符號字符型數(shù)據(jù)的空指針。
CWORD是指向程序存儲器空間(64KB)中無符號整型數(shù)據(jù)(2B)的空指針。DWORD是指向片內直接尋址數(shù)據(jù)存儲器空間(128B)中無符號整型數(shù)據(jù)(2B)的空指針。
PWORD是指向片外數(shù)據(jù)存儲器分頁訪問空間(256B)中無符號整型數(shù)據(jù)(2B)的空指針。
XWORD是指向片外數(shù)據(jù)存儲器空間(64KB)中無符號整型數(shù)據(jù)(2?B)的空指針。
只要在程序文件中使用“include<absacc.h>”,在C程序中就可以用空指針來定義絕對地址變量,訪問絕對地址單元的數(shù)據(jù)。
例如,利用absacc.h中宏定義指針來定義一個擴展8255端口,設控制口、A口、B口、C口地址分別為007Fh、007Ch、007Dh、007Eh。
#defineCOM8255XBYTE[0X007F]
#definePA8255XBYTE[0X007C]
#definePB8255XBYTE[0X007D]
#definePC8255XBYTE[0X007E]經上述定義后,就可以用COM8255、PA8255、PB8255、PC8255分別表示端口地址,直接進行端口操作。如:
COM8255=0X0F;
是將命令字0FH輸出到8255控制口。
還可以直接訪問存儲器地址單元。例如:
cval=DBYTE[0x0002]
;把程序存儲器0002H地址單元的無符號字符型數(shù)據(jù)賦給變量
dval=XWORD[0x0004]
;把外數(shù)據(jù)存儲器0004H地址單元的整形數(shù)據(jù)(2B)賦給變量
3.intrins.h
C51提供了模擬51單片機指令系統(tǒng)中空操作、位測試、移位、堆棧操作指令功能的函數(shù),在intrins.h中對這些函數(shù)原型進行說明。
intrins.h的主要內容如下:只要在程序文件中使用“include<intrins.h>”,在C程序中就可以調用其中的函數(shù),實現(xiàn)相應匯編指令的功能。例如:
#include<intrins>h>
main()
{
unsignedinty;
y=0X000F;
y=_irol_(y,4);
}
程序執(zhí)行后,y的值左移4位,變?yōu)?0F0H。
8.951單片機內部資源應用的C語言編程
8.9.1中斷應用的C語言編程
C51編譯器支持在C源程序中直接開發(fā)中斷程序。中斷服務程序是按規(guī)定語法格式定義的一個函數(shù)。定義中斷服務函數(shù)的一般形式如下:
返回值函數(shù)名([參數(shù)])interruptm[usingn]
{
}
其中:返回值、函數(shù)名([參數(shù)])部分與標準C語言中的意義相同。
interruptm用于選擇中斷號。m表示中斷源的中斷號,取值為0~31的常整數(shù),不允許使用表達式。51單片機中斷源編號如表8.7所示。
usingn選項用于工作寄存器組的切換,n是中斷服務子程序中選用的工作寄存器組號(0~3)。在許多情況下,響應中斷時需保護有關現(xiàn)場信息,以便中斷返回后,能使被中斷的程序從斷點處繼續(xù)正確地執(zhí)行下去。在51單片機中,能很方便地利用工作寄存器組的切換來實現(xiàn)現(xiàn)場信息保護,即在進入中斷服務程序前的程序中使用一組工作寄存器,進入中斷服務程序后,由“usingn”切換到另一組寄存器,中斷返回后又恢復到原寄存器組。這樣互相切換的兩組寄存器中的內容彼此都沒有被破壞。在函數(shù)體中進行相應中斷事務處理。
例1
圖8.3所示是利用優(yōu)先權解碼芯片,在單片機8051的外部中斷上擴展多個中斷源的原理電路圖。圖中是以開關閉合來模擬中斷請求信號。當有任一中斷源產生中斷請求時,能給8051的送一個有效中斷信號,由P1的低3位可得對應中斷源的中斷號。圖8.3擴展多個中斷源在中斷服務程序中僅設置標志,并保存I/O口輸入狀態(tài)。C51程序如下:本例中說明了一個重要的中斷處理技術。在實際中斷系統(tǒng)中,如果中斷處理程序比較長,放在中斷服務程序中進行處理,可能會延長甚至會丟掉比該中斷優(yōu)先級低的中斷請求。為了提高中斷響應速度,只在中斷服務程序中為該中斷建立中斷標志,而把中斷處理放在主程序中作為背景程序,根據(jù)中斷標志決定是否被執(zhí)行。8.9.2定時器/計數(shù)器應用的C語言編程
例2
設單片機的fosc=12MHz晶振,要求在P1.0腳上輸出周期為2ms的方波。周期為2ms的方波要求定時時間隔
1ms時對P1.0取反輸出。
(1)用定時器0的方式1編程,采用查詢方式,程序如下:(2)用定時器0的方式1編程,采用中斷方式。程序如下:
例3
采用12?MHz晶振,在P1.0腳上輸出周期為2.5?s,占空比為20%脈沖信號。
12?MHz晶振,使用定時器10?ms。周期2.5?s需250次中斷,占空比20%,高電平應為50次中斷。中斷服務程序流程圖如圖8.4所示。圖8.4中斷服務程序流程圖8.9.3串行口使用的C語言編程
單片機的串行口可用于與通用微機的通信、單片機間的通信和主從結構的分布式系統(tǒng)機間的通信。
例4
單片機fosc?=?11.0592?MHz,波特率為9600,各設置32字節(jié)的隊列緩沖區(qū)用于發(fā)送接收。設計單片機和終端或另一計算機通信的程序。
編寫程序前的設計工作:
(1)用定時器1工作方式2,作比特率發(fā)生器。根據(jù)以下公式計算初值,設初值為x。溢出率=波特率×32(SMOD=0)
(2)設置接收和發(fā)送隊列緩沖區(qū)32字節(jié),定義接收隊列入隊和出隊操作指示變量rin和rout、發(fā)送隊列入隊和出隊操作指示變量tin和tout,設置接收隊接滿(r_fuu)、發(fā)送隊列空(t_empty)、發(fā)送完成(t_done)標志變量。利用這些變量來管理隊列操作。
(3)功能模塊規(guī)劃。loadmsg函數(shù)向發(fā)送隊列加載數(shù)據(jù)串;processmsg函數(shù)對接收隊列中的數(shù)據(jù)進行處理;從串行口SBUF讀取數(shù)據(jù)或向SBUF傳送數(shù)據(jù)的操作在中斷處理程序中完成。在主函數(shù)中初始化定時器,初始化串行口、調用隊列裝載和處理函數(shù)。
具體程序如下:
8.1051單片機片外擴展的C語言編程
8.10.18255與單片機接口C語言程序
例5
通過擴展8255接口控制打印機。
圖8.5是51單片機擴展8255與打印機接口的電路。打印機與單片機采用查詢方式交換數(shù)據(jù)。BUSY為打印機的狀態(tài)信號,打印機忙時BUSY?=?1,空閑時BUSY?=?0。微型打印機的數(shù)據(jù)輸入采用選通控制,當產生負跳變時數(shù)據(jù)進入打印機。圖8.551單片機擴展8255A與打印機接口按照接口電路,只要單片機從P0.7傳送的第7位地址為0即可選中8255。這就確定了A口地址為0xxxxx00。取7CH作A口地址,則B、C、控制口地址分別為7DH、7EH、7FH。A口作為向打印機傳送數(shù)據(jù)的輸出口,從PC7輸入打印機的狀態(tài)信號,PC0產生選通控制信號,可設置PC7~PC4為輸入,PC3~PC0為輸出。方式字設置為10001xx0,取8EH作方式控制字。向打印機輸出字符串“WELCOME”的程序如下:8.10.251單片機數(shù)據(jù)采集的C語言編程
例6ADC0809與51單片機接口的數(shù)據(jù)采集程序。
按圖8.6所示接口電路,編寫從ADC0809的8通道輪流采集一次數(shù),采集的結果放在數(shù)組ad中的程序。圖8.6ADC0809與51單片機的接口電路按照圖中片選線的連接,ADC0809的模擬通道0地址應為:0××××××××××××000。取8個通道地址:7FF8H~7FFFH。
程序如下:
例7AD574與51單片機接口的數(shù)據(jù)采集程序。
按圖8.7所示的接口電路,進行12位分辨的模擬信號采集。啟動AD574進行一次轉換,編寫一個獨立函數(shù),調用此函數(shù)可得轉換結果。
AD574轉換程序如下:圖8.7AD574與51單片機的接口電路
例851單片機與TLC0831接口的數(shù)據(jù)轉換程序。
51單片機與TLC0831接口電路如圖8.8所示。
圖8.8TLC0831與51單片機的接口TLC0832源程序如下:
#include<reg52.h>
#include<stdio.h>
#include<absacc.h>
#defineucharunsignedchar
#defineuintunsignedint
sbitadcdo=P1^2; /*定義數(shù)據(jù)線位變量*/
sbitadccs=P1^0; /*定義片選信號線位變量*/
sbitadcclk=P1^1; /*定義時鐘線位變量*/8.10.351單片機輸出控制的C語言編程
例951單片機與DAC0832單緩沖區(qū)接口的數(shù)據(jù)轉換。
接口電路如圖8.9所示。在單片機執(zhí)行輸出指令時,只要從地址總線上傳送地址的最低位為0,使和有效,即可實現(xiàn)數(shù)據(jù)鎖存與啟動。圖8.9DAC0832與51單片機的單緩沖接口電路控制DAC0832轉換,輸出一個鋸齒波電壓信號的C51程序如下:例1051單片機與DAC0832雙緩沖接口的數(shù)據(jù)轉換程序。
接口電路如圖8.10所示。在單片機執(zhí)行輸出指令時,只要從地址總線上傳送相應地址,即可選通DAC0832相應鎖存器,實現(xiàn)啟動轉換控制。第一片的輸入寄存器(一級緩沖器)地址為10001×××××××××××,取8FFFH。第一片的輸入鎖存器(一級緩沖器)地址為10100×××××××
××××,取A7FFH。兩片的DAC鎖存器(二級緩沖器)具有相同地址00101×××××××××××,取2FFFH。圖8.10DAC0832雙緩沖接口電路將data1和data2數(shù)據(jù)同步轉換為模擬量的C51程序如下:
例1151單片機與AD7521接口的數(shù)據(jù)轉換程序。
接口電路如圖8.11所示。AD7521是12位轉換器,從B1~B12接收12位數(shù)字量即可啟動轉換。它與51單片機接口,必須在外部設計兩級緩沖器,以實現(xiàn)分步轉送數(shù)據(jù),同步啟動。圖中用兩片74LS377鎖存器作為低8位數(shù)據(jù)的兩級緩沖器,74LS379作高4位數(shù)據(jù)緩沖器。從圖可知,在單片機執(zhí)行輸出指令時,從地址總線傳送相應地址,可分別選通緩沖器。第一級8位緩沖器的選通地址是0×××××××××××××××,取7FFFH。第二級8位緩沖器和4位緩沖器為同一選通地址×0××××××××××××××,取BFFFH。單片機輸出低8位數(shù)據(jù),先鎖存到第一級緩沖器中,接著輸出高4位數(shù)據(jù),在鎖存高4位數(shù)據(jù)的同時低8位數(shù)據(jù)也鎖存到第二級緩沖器,12位數(shù)據(jù)同時達到AD7521,啟動轉換。
使AD7521輸出梯形波的C51程序如下:圖8.1151單片機與AD5721的接口
例1251單片機與串行D/A轉換器MAX517接口的數(shù)據(jù)轉換程序。
MAX517接口電路如圖8.12所示。
轉換程序就是在單片機的P1.0和P1.1口線上模擬產生I2C總線標準的工作時序,向MAX517發(fā)送數(shù)據(jù),控制轉換。51單片機為主設備,首先單片機向MAX517發(fā)送一個地址字節(jié)58H,等待應答后再發(fā)一個控制字節(jié)00H,再次等待應答之后,再發(fā)要轉換的8位數(shù)據(jù)。圖8.1251單片機與MAX517的接口控制MAX517轉換的C51程序如下:
8.11頻率、周期測量的C語言編程
8.11.1測量頻率
測量頻率法是指在單位時間內對被測信號進行計數(shù)。測量頻率法最簡單的接口電路是將頻率脈沖直接連接到51單片機的T1端,用單片機的C/T0作定時器,用C/T1作計數(shù)器。在定時時間里,對頻率脈沖進行計數(shù)。T/C1的計數(shù)值便是單位定時時間里的脈沖個數(shù)。在計數(shù)時會出現(xiàn)如圖8.13所示的丟失脈沖的情況。第一個丟失的脈沖,是由于開始檢測時脈沖寬度小于機器周期T;第二個丟失的脈沖是由于脈沖的負跳變在定時之外。定時時間內出現(xiàn)脈沖丟失,將引起測量精度降低。脈沖頻率越低,這種錯誤越大。顯然對于較低頻率的脈沖測量,最不適合采用測量頻率法。圖8.13測量頻率中的脈沖丟失
例13
帶同步控制的頻率測量。
為解決圖8.13中的第一個脈沖丟失,可用門電路實現(xiàn)計數(shù)開始與脈沖上升沿的同步控制。51單片機的T/C0作定時器,T/C1作計數(shù)器,對fx的頻率測量接口電路如圖8.14所示。圖8.14帶同步控制的頻率測量接口8.11.2測量周期
測量周期的基本原理是在被測信號周期T內,對某一已知周期的脈沖信號進行計數(shù),已知周期與計數(shù)值的乘積便是被測信號周期。這種測量要求在被測周期開始啟動計數(shù),周期結束時停止計數(shù)??捎脠D8.15所示接口電路來實現(xiàn)測量。
74LS74是一個雙D觸發(fā)器芯片,圖中連接是利用其中的一個觸發(fā)器將被測信號的周期轉換成圖8.16所示的分頻信號。Q端輸出的分頻信號接單片機的外部中斷0上。用單片機T/C0的門控方式,在被測信號的一個周期內,對內部機器周期信號進行計數(shù)。測量時,從P1.0輸出0,清除D觸發(fā)器,Q端輸出為0,定時器不能啟動。在被測信號上升沿到來時,Q端輸出高電平,此時啟動定時器對內部機器周期計數(shù)。在被測信號的第一個周期內Q端保持高電平,周期結束時變?yōu)榈碗娖?,停止定時器計數(shù),同時產生中斷請求。在中斷程序中,讀取計數(shù)值,即可測量出被測信號的周期。圖8.15周期測量接口圖8.16頻率周期波形
8.1251單片機間通信的C語言編程
8.12.1點對點的串行異步通信
1.通信雙方的硬件連接
如果采用單片機自身的TTL電平直接傳輸信息,其傳輸距離一般不超過1.5m。51單片機一般采用RS-232C標準進行點對點的通信連接。圖8.17是兩個51單片機間的連接方法,信號采用RS-232C電平傳輸,電平轉換芯片采用MAX232。
2.通信雙方的約定
按照圖8.17所示的接口電路。假定A機SYSTEM1是發(fā)送者,B機SYSTEM2是接收者。當A機開始發(fā)送時,先送一個“AA”信號,B機收到后回答一個“BB”,表示同意接收。當A機收到“BB”后,開始發(fā)送數(shù)據(jù),每發(fā)送一次求“校驗和”,假定數(shù)據(jù)塊長度為16個字節(jié),數(shù)據(jù)緩沖區(qū)為buf,數(shù)據(jù)塊發(fā)送完后馬上發(fā)送“校驗和”。
B機接收數(shù)據(jù)并將其轉存到數(shù)據(jù)緩沖區(qū)buf,每接收到一個數(shù)據(jù)便計算一次“校驗和”,當接收完一個數(shù)據(jù)塊后,再接收A機發(fā)來的校驗和,并將它與B機求出的校驗和進行比較。若兩者相等,說明接收正確,B機回答00H;若
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 醫(yī)院信息管理系統(tǒng)的設計與實施
- 醫(yī)療信息安全管理體系構建與實踐
- 醫(yī)療信息系統(tǒng)中基于區(qū)塊鏈的薪酬激勵模式
- 區(qū)塊鏈助力金融交易流程優(yōu)化探討
- 從臨床到研究化學實驗室的創(chuàng)新實踐
- 本科畢業(yè)生實習總結模版
- 區(qū)塊鏈技術在數(shù)據(jù)安全與隱私保護的應用
- 女媧補天(教學設計)
- 范稿模板17財務出納年終工作總結模版
- 買賣小商鋪合同范例
- 2024北京朝陽城市發(fā)展集團有限公司社會化招聘專場筆試參考題庫附帶答案詳解
- 山東臨沂市羅莊區(qū)興羅投資控股有限公司招聘筆試題庫2025
- 亞馬遜代運營合同樣本
- 低空經濟產業(yè)園的戰(zhàn)略意義
- 金屬鑄造企業(yè)熔煉過程中的安全控制
- 2024年至2025年山東省泰安市公開招聘警務輔助人員輔警結構化面試必練經典模擬題庫一含答案
- 汽修廠三人合伙協(xié)議
- 金融法律知識培訓課件
- 《亞洲文化概覽》課件
- 《廢品創(chuàng)意與制作》(教學設計)-2024-2025學年四年級上冊綜合實踐活動教科版
- 2024年食品檢驗員(三級)技能理論考試復習題庫(含答案)
評論
0/150
提交評論