我們?cè)谟?/span>c語(yǔ)言編程時(shí)往往第一行就是頭文件,51單片機(jī)為reg51.h或reg52.h,51單片機(jī)相對(duì)來(lái)說(shuō)比較簡(jiǎn)單,頭文件里面內(nèi)容不多,像飛思卡爾、ARM系列的單片機(jī)頭文件往往內(nèi)容就非常多,盡管如此,對(duì)一些初次接觸單片機(jī)的朋友來(lái)說(shuō),51的頭文件還是搞不太清楚,今天具體來(lái)說(shuō)明一下。
1)“文件包含”處理概念
所謂“文件包含”是指在一個(gè)文件內(nèi)將另外一個(gè)文件的內(nèi)容全部包含進(jìn)來(lái)。因?yàn)楸话奈募械囊恍┒x和命令使用的頻率很高,幾乎每個(gè)程序中都可能要用到,為了提高編程效率,減少編程人員的重得勞動(dòng),將這些定義和命令單獨(dú)組成一個(gè)文件,如reg51.h,然后用#include<reg51.h>包含進(jìn)來(lái)就可以了,這個(gè)就相當(dāng)于工業(yè)上的標(biāo)準(zhǔn)零件,拿來(lái)直接用就可以了。
2)寄存器地址及位地址聲明的原因
reg51.h里面主要是一些特殊功能寄存器的地址聲明,對(duì)可以位尋址的,還包括一些位地址的聲明,如果如sfr P1=0x80; sfr IE=0xA8;sbit EA=0xAF等。
sfr P1 = 0x90這句話表示:P1口所對(duì)應(yīng)的特殊功能寄存器P1在內(nèi)存中的地址為0x80,sbit EA=0xAF這句話表示EA這一位的地址為0xAF。
注意這里出現(xiàn)了一個(gè)使用很頻繁的sfr和sbit。
sfr 表示特殊功能寄存器的意思,它并非標(biāo)準(zhǔn)C 語(yǔ)言的關(guān)鍵字,而是Keil 為能直接訪問80C51 中的SFR 而提供了一個(gè)新的關(guān)鍵詞,其用法是:sfr 特殊功能寄存器名=地址值(注意對(duì)于頭文件里“特殊功能寄存器名”,用戶實(shí)際上也可以修改的,如P1=0x80,也可改為A1=0x80,但sfr 和地址值則不能更改,否者會(huì)編譯出錯(cuò)。)
sbit 表示位的意思,它也是非標(biāo)準(zhǔn)C 語(yǔ)言的關(guān)鍵字,編寫程序時(shí)如需操作寄存器的某一位(可位尋址的寄存器才能用)時(shí),需定義一個(gè)位變量,此時(shí)就要要到sbit,如sbit deng=P1^0,sbit EA = 0xAF;需要注意的是,位定義時(shí)有些特殊, 用法有三種:
第一種方法:sbit 位變量名=寄存器位地址值
第二種方法:sbit 位變量名=SFR 名稱^寄存器位值(0-7)
第三種方法:sbit 位變量名=SFR 地址值^寄存器位值
如:
sbit IT0=0x88 (1)說(shuō)明:0x88是IT0 的位地址值
sbit deng=P1^2 (2)說(shuō)明:其中P1 必須先用sfr 定義好
sbit EA=0xA8^7 (3)說(shuō)明:0xA8 就是IE寄存器的地址值
以上三種定義方法需注意的是 IT0 deng EA可由用戶隨便定義,但必須滿足C語(yǔ)言對(duì)變量名的定義規(guī)則。除些外其它的則必須按照上面的格式寫,如“名稱^變量位地址值”中“^”,它是由keil軟件的規(guī)定的 ,不能寫成其它的,只能這樣能才編譯通過。
以上是對(duì)寄存器地址和位地址的定義和聲明作了解釋,大家需要牢牢記。只有對(duì)寄存器及相關(guān)位進(jìn)行聲明地址后,我們才能對(duì)其進(jìn)行賦相關(guān)的值,keil軟件才能編譯通過。至于說(shuō)為什么,這可能一句話兩句話也說(shuō)不清楚。
3)內(nèi)存、SFR、位、地址等的通俗解釋
前面講到了寄存器地址和位地址(前提能位尋址)聲明的目的是為告訴C編譯器相應(yīng)寄存器及其位在內(nèi)存中的地址,這樣我們對(duì)寄存器及一些位賦的變量和數(shù)值才能正確保存,然后才能供CPU正確的調(diào)用,完成相應(yīng)的功能。
上段文字出現(xiàn)了寄存器(SFR)、位,地址、內(nèi)存等,單片機(jī)學(xué)習(xí)過程中還會(huì)出現(xiàn)ROM、RAM等名詞,可能大家覺得不是很好理解,這里可以通俗的解釋一下,如下面三個(gè)圖所示。
我們把內(nèi)存比作賓館,ROM、RAM、SFR相當(dāng)于賓館里具體的有三種不同功能樓層(具體這個(gè)賓館多少層即多少ROM、RAM、SFR,視各個(gè)賓館或者每種單片機(jī)而不同),每層8個(gè)房間相當(dāng)于8位,每個(gè)房間要么住男人要么住女人相當(dāng)于每位要么放入數(shù)字1要么放入數(shù)字0,keil編譯器就相當(dāng)于賓館的工作人員,旅客去住旅館相當(dāng)寫程序的過程,住賓館的人必須事先要給工作人員說(shuō)你是哪一層哪一個(gè)房間(即聲明寄存器地址和位地址,)賓館工作人員才能把你帶到你的房間里去(這里假設(shè)這個(gè)賓館可以由旅客自己決定住哪個(gè)房間)。即:只有對(duì)寄存器及相關(guān)位進(jìn)行聲明地址后,我們才能對(duì)其進(jìn)行賦相關(guān)的值,keil軟件才能編譯通過。
4)REG51.H頭文件原文及解釋
打開reg51.h 可以看到這樣的一些內(nèi)容(此文件一般在C:\KEIL\C51\INC下 ,INC文件夾根目錄里有不少頭文件,并且里面還有很多以公司分類的文件夾,里面也都是相關(guān)產(chǎn)品的頭文件。如果我們要使用自己寫的頭文件,使用的時(shí)候只需把對(duì)應(yīng)頭文件拷貝到INC文件夾里就可以了。)
下面附出頭文件的原文,并把注釋文件一并附后。
/*--------------------------------------------------------------------------
REG51.H
Header file for generic 80C51 and 80C31 microcontroller.
Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.
All rights reserved.
--------------------------------------------------------------------------*/
#ifndef __REG51_H__
#define __REG51_H__
/* BYTE Register */
sfr P0 = 0x80; //三態(tài)雙向 IO口 P0口 此句話的意思是:特殊功能寄存器。校啊〉刂窞椋皒80 ,可位尋址,下同
//低8位地址總線/數(shù)據(jù)總線(一般不用而只作普通I/O口,注意作I/O口用時(shí),硬件上需接上接電阻)
sfr P1 = 0x90; //準(zhǔn)雙向 IO口 P1口
sfr P2 = 0xA0; //準(zhǔn)雙向 IO口 P2口
//高8位地址總線,一般也作普通I/O用
sfr P3 = 0xB0; //雙功能
//1.準(zhǔn)雙向 IO口 P3口
//2. P30 RXD串行數(shù)據(jù)接受
// P31 TXD串行數(shù)據(jù)發(fā)送
// P32 外部中斷0 信號(hào)申請(qǐng)
// P33 外部中斷1 信號(hào)申請(qǐng)
// P34 定時(shí)/計(jì)數(shù)器T0 外部計(jì)數(shù)脈沖輸入
// P35 定時(shí)/計(jì)數(shù)器T1 外部計(jì)數(shù)脈沖輸入
// P36 WR 片外RAM寫脈沖信號(hào)輸入
// P37 RD 片外ram讀脈沖信號(hào)輸入
sfr PSW = 0xD0; // 可以位尋址(C語(yǔ)言編程時(shí)可不考慮此寄存器)
//程序狀態(tài)寄存器Program Status WORD (程序狀態(tài)信息)
//psw.7(CY) 進(jìn)位標(biāo)志
//psw.6(AC)輔助進(jìn)位標(biāo)志位低四位向高四位進(jìn)位或借位時(shí) AC=1
//主要用于十進(jìn)制調(diào)整
//psw.5(F0)用戶可自定義的程序標(biāo)志位
//psw.4(RS1)
//psw.3(RS0)
//工作寄存器選擇位
//任一時(shí)刻只有一組寄存器在工作
//0 0 0區(qū) 00H~07H
//0 1 1區(qū) 08H~0fH
//1 0 2區(qū) 10H~17H
//1 1 3區(qū) 18H~1FH
//psw.2(OV) 溢出標(biāo)志位
//psw.1( ) 保留為 ,不可使用
//psw.0(P) 奇偶校驗(yàn)位
sfr ACC = 0xE0; //累加器A 特殊功能寄存器 可位尋址
sfr B = 0xF0; //寄存器B 主要用于乘除運(yùn)算
sfr SP = 0x81; //堆棧指針寄存器SP 存放站定棧頂?shù)刂贰?/span>
sfr DPL = 0x82; //
sfr DPH = 0x83; //數(shù)據(jù)指針寄存器DPTR、//對(duì)片外RAM及擴(kuò)展IO進(jìn)行存取用的地址指針
sfr PCON = 0x87; //電源控制寄存器 、不能位尋址
//管理單片機(jī)的電源部分包括上電復(fù)位、掉電模式、空閑模式等
//單片機(jī)復(fù)位時(shí)PCON被全部清0,編程時(shí)一般是用到SMOD位,其它的一般不用
//D7 SMOD該位與串口通信波特率有關(guān)
//SMOD=0 串口方式1 2 3 波特率正常
//SMOD=1 串口方式1 2 3 波特率加倍
sfr TCON = 0x88; //定時(shí)器/計(jì)數(shù)器 控制寄存器 可以位尋址
//D7 TF1 定時(shí)器1溢出標(biāo)志位
//D6 TR1 定時(shí)器1運(yùn)行控制位
//D5 TF0 定時(shí)器0溢出標(biāo)志位
//D4 TR0 定時(shí)器0運(yùn)行控制位
//D3 IE1 外部中斷1請(qǐng)求標(biāo)志
//D2 IT1 外部中斷1 觸發(fā)方式選擇位
//D1 IE0 外部中斷0請(qǐng)求標(biāo)志
//D0 IT0 外部中斷0 觸發(fā)方式選擇位
sfr TMOD = 0x89; //定時(shí)器/計(jì)數(shù)器 工作方式寄存器 不能位尋址
//確定工作方式和功能
//D7 GATE 門控制位
//GATE=0;定時(shí)器/計(jì)數(shù)器由TRX(x=0,1)來(lái)控制
//GATE=1;定時(shí)器/計(jì)數(shù)器由TRX(x=0,1)
//和外部中斷引腳(init0,1)來(lái)共同控制
//D6 C/T 定時(shí)器、計(jì)數(shù)器選擇位
// 0 選擇定時(shí)器模式
// 1 選擇計(jì)數(shù)器模式
//D5 M1
//D4 M0
//M1 M0 工作方式
//0 0 方式0 13位定時(shí)器/計(jì)數(shù)器
//0 1 方式1 16位定時(shí)器/計(jì)數(shù)器
//1 0 方式2 8位自動(dòng)重裝定時(shí)器/計(jì)數(shù)器
//1 1 方式3 僅適用T0 分成兩個(gè)8位計(jì)數(shù)器,T1停止計(jì)數(shù)
//D3 GATE 門控制位
//GATE=0;定時(shí)器/計(jì)數(shù)器由TRX(x=0,1)來(lái)控制
//GATE=1;定時(shí)器/計(jì)數(shù)器由TRX(x=0,1)
//和外部中斷引腳(init0,1)來(lái)共同控制
//D2 C/T 定時(shí)器、計(jì)數(shù)器選擇位
//0 選擇定時(shí)器模式
//1 選擇計(jì)數(shù)器模式
//D1 M1
//D0 M0
// M1 M0 工作方式
// 0 0 方式0 13位定時(shí)器/計(jì)數(shù)器
// 0 1 方式1 16位定時(shí)器/計(jì)數(shù)器
// 1 0 方式2 8位自動(dòng)重裝定時(shí)器/計(jì)數(shù)器
// 1 1 方式3 僅適用T0 分成兩個(gè)8位計(jì)數(shù)器,T1停止計(jì)數(shù)
sfr TL0 = 0x8A; //定時(shí)器/計(jì)數(shù)器0高8位 容器 加1 計(jì)數(shù)器
sfr TL1 = 0x8B; //定時(shí)器/計(jì)數(shù)器1高8位 容器
sfr TH0 = 0x8C; //定時(shí)器/計(jì)數(shù)器0低8位 容器
sfr TH1 = 0x8D; //定時(shí)器/計(jì)數(shù)器1低8位 容器
sfr IE = 0xA8; //中斷允許寄存器 可以位尋址
//D7 EA 全局中斷允許位
//D6 NULL
//D5 ET2 定時(shí)器/計(jì)數(shù)器2中斷允許位 interrupt 5
//D4 ES 串行口中斷允許位 interrupt 4
//D3 ET1 定時(shí)器/計(jì)數(shù)器1中斷允許位 interrupt 3
//D2 EX1 外部中斷1中斷允許位 interrupt 2
//D1 ET0 定時(shí)器/計(jì)數(shù)器0中斷允許位 interrupt 1
//D0 EX0 外部中斷0中斷允許位 interrupt 0
sfr IP = 0xB8; //中斷優(yōu)先級(jí)寄存器 可進(jìn)行位尋址
//D7 NULL
//D6 NULL
//D5 NULL
//D4 PS 串行口中斷定義優(yōu)先級(jí)控制位
// 1 串行口中斷定義為高優(yōu)先級(jí)中斷
// 0 串行口中斷定義為低優(yōu)先級(jí)中斷
//
//D3 PT1
// 1 定時(shí)器/計(jì)數(shù)器1中斷定義為高優(yōu)先級(jí)中斷
// 0 定時(shí)器/計(jì)數(shù)器1中斷定義為低優(yōu)先級(jí)中斷
//D2 PX1
// 1 外部中斷1定義為高優(yōu)先級(jí)中斷
// 0 外部中斷1定義為低優(yōu)先級(jí)中斷
//D1 PT0
// 1 定時(shí)器/計(jì)數(shù)器0中斷定義為高優(yōu)先級(jí)中斷
// 0 定時(shí)器/計(jì)數(shù)器0中斷定義為低優(yōu)先級(jí)中斷
//D0 PX0
// 1 外部中斷0定義為高優(yōu)先級(jí)中斷
// 0 外部中斷0定義為低優(yōu)先級(jí)中斷
sfr SCON = 0x98; //串行口控制寄存器 可以進(jìn)行位尋址
//D7 SM0
//D6 SM1
// SM0 SM1 串行口工作方式
// 0 0 同步移位寄存器方式
// 0 1 10位異步收發(fā)(8位數(shù)據(jù)),波特率可變(定時(shí)器1溢出率控制)
// 1 0 11位異步收發(fā)(9位數(shù)據(jù)),波特率固定
// 1 1 11異步收發(fā)(9位數(shù)據(jù)) ,波特率可變(定時(shí)器1溢出率控制)
//D5 SM2 多機(jī)通信控制位 主要用于方式2和方式3
//D4 REN 允許串行接收位
//D3 TB8 方式2,3中發(fā)送數(shù)據(jù)的第9位
//D2 RB8 方式2,3中接受數(shù)據(jù)的第9位
//D1 TI 發(fā)送中斷標(biāo)志位
//D0 RI 接受中斷標(biāo)志位
sfr SBUF = 0x99; //串行數(shù)據(jù)緩沖區(qū)
/*****************************************************************************
下面是位尋址區(qū)
上面做過解釋的就不在下面一一解釋了
******************************************************************************/
/* BIT Register */
/* PSW */
sbit CY = 0xD7;
sbit AC = 0xD6;
sbit F0 = 0xD5;
sbit RS1 = 0xD4;
sbit RS0 = 0xD3;
sbit OV = 0xD2;
sbit P = 0xD0;
/* TCON */
sbit TF1 = 0x8F;
sbit TR1 = 0x8E;
sbit TF0 = 0x8D;
sbit TR0 = 0x8C;
sbit IE1 = 0x8B;
sbit IT1 = 0x8A;
sbit IE0 = 0x89;
sbit IT0 = 0x88;
/* IE */
sbit EA = 0xAF;
sbit ES = 0xAC;
sbit ET1 = 0xAB;
sbit EX1 = 0xAA;
sbit ET0 = 0xA9;
sbit EX0 = 0xA8;
/* IP */
sbit PS = 0xBC;
sbit PT1 = 0xBB;
sbit PX1 = 0xBA;
sbit PT0 = 0xB9;
sbit PX0 = 0xB8;
/* P3 */
sbit RD = 0xB7;
sbit WR = 0xB6;
sbit T1 = 0xB5;
sbit T0 = 0xB4;
sbit INT1 = 0xB3;
sbit INT0 = 0xB2;
sbit TXD = 0xB1;
sbit RXD = 0xB0;
/* SCON */
sbit SM0 = 0x9F;
sbit SM1 = 0x9E;
sbit SM2 = 0x9D;
sbit REN = 0x9C;
sbit TB8 = 0x9B;
sbit RB8 = 0x9A;
sbit TI = 0x99;
sbit RI = 0x98;
#endif