單片機sfr和sbit詳解
sfr用于將一個單片機的特殊功能寄存器(special function register)賦值給一個變量,這樣在后面的程序中就可以中這個變量指引(refer to)該寄存器。
sbit與sfr用法類似,只是sbit是位操作,用于將某個sfr中具體位賦值給一個變量,這樣后面程序就可用通過該變量為該位清0或置1。
STC該系列單片機的特殊功能寄存器布局如下:
看過圖1這么多特殊功能寄存器之后可能會產生一些困擾,我們用sfr P0 = 0×80表示P0,用sfr SP = 0×81表示SP,這個沒有歧義。有困擾的是:假如用sbit P0_1 = 0×81表示P0口的第一位,那么我想表示SP寄存器的第0位怎么辦呢?如果也是定義成sbit SP_0 = 0×81那么明顯會有二義性,編譯器理解不了。其實這個問題是不存在的,從圖1中可以看出,SFR又可以分為兩個區域:可位尋址區和不可位尋址區。可位尋址區的寄存器地址能夠被8整除,而不可位尋址區的寄存器地址不滿足這一要求。因此例子中的sbit SP_0 = 0×81對于SP寄存器這是無效的應該寫成sfr SP=0x81。
例如:sbit P1^1=0x81;sfr SP=0x81;
它們雖然都引用了同一個地址0×81,但是對于編譯器來說,這兩者的含義完全不同,前者因為有sfr關鍵字,所以是字節地址。后者因為是sbit關鍵字,所以是位尋址,表示的是一個bit。
sfr(Special Function Register特殊功能寄存器的縮寫),sbit(特殊功能寄存器位),與定義一般的int、char型變量不同,這兩個字定義的并不是變量,而作為特殊功能寄存器的引用,或許可以叫做別名。
單片機頭文件《reg51.h》中定義了21個特殊功能寄存器,并且都是8位寄存器,而部分寄存器的每個位又用sbit進行了定義:
?。踓pp] view plain copysfr P0 = 0x80;
sfr P1 = 0x90;
sfr P2 = 0xA0;
sfr P3 = 0xB0;
sfr PSW = 0xD0;
sfr ACC = 0xE0;
sfr B = 0xF0;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
sfr PCON = 0x87;
sfr TCON = 0x88;
sfr TMOD = 0x89;
sfr TL0 = 0x8A;
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
sfr IE = 0xA8;
sfr IP = 0xB8;
sfr SCON = 0x98;
sfr SBUF = 0x99;
sfr是定義一個8位的寄存器,sbit是定義位寄存器,個人認為可以把這種定義理解為定義一個常量指針始終指向0x80這個特殊寄存器,即如下定義方法;
?。踓pp] view plain copyconst unsigned char *PP = 0x80;
當然,這種定義方法不完全符合上面的說法,而且*PP被限制了寫操作的,即PP所指向的地址被認定為常量,而PP任然是個變量,事實上除了使用sfr和sbit進行定義外,其他定義方式被認為是不安全的而被限制了寫入操作。最后發現定義指針的時候只有定義數組時:
?。踓pp] view plain copychar a[];
地址指針a才是一個常量指針,而其他指針都是變量;
c51中sbit/sfr 用法
1 首先區分bit 和sbit
bit和int char之類的差不多,只不過char=8位, bit=1位而已。都是變量,編譯器在編譯過程中分配地址。除非你指定,否則這個地址是隨機的。這個地址是整個可尋址空間,RAM+FLASH+擴展空間。bit只有0和1兩種值,意義有點像Windows下VC中的BOOL。
sbit是對應可位尋址空間的一個位,可位尋址區:20H~2FH。一旦用了sbi xxx = REGE^6這樣的定義,這個sbit量就確定地址了。sbit大部分是用在寄存器中的,方便對寄存器的某位進行操作的。
sbit的用法有三種:
第一種方法:sbit 位變量名=地址值
第二種方法:sbit 位變量名=SFR名稱^變量位地址值
第三種方法:sbit 位變量名=SFR地址值^變量位地址值
如定義PSW中的OV可以用以下三種方法:
sbit OV=0xd2 (1)說明:0xd2是OV的位地址值
sbit OV=PSW^2 (2)說明:其中PSW必須先用sfr定義好
sbit OV=0xD0^2 (3)說明:0xD0就是PSW的地址值
因此這里用sfr P1_0=P1^0;就是定義用符號P1_0來表示P1.0引腳,如果你愿意也可以起P10一類的名字,只要下面程序中也隨之更改就行了。
注意:“^”實質代表的是異或運算,可以算一下,恰好符合。
2.Sfr用法
sfr 似乎不是標準C 語言的關鍵字,而是Keil 為能直接訪問80C51 中的SFR 而提供了一個新的關鍵詞,其用法是:sfrt 變量名=地址值。
例:sfr P1 = 0x90;
這樣的一行即定義P1 與地址0x90 對應,P1 口的地址就是0x90.
SFR的定義在頭文件reg51.h或reg52.h中。
?。跭eil 幫助]
sfr Types
SFRs are declared in the same fashion as other C variables. The ONLY difference is that the data type specified is sfr rather than CHAR or int. For example:
sfr P0 = 0x80; /* Port-0, address 80h */
sfr P1 = 0x90; /* Port-1, address 90h */
sfr P2 = 0xA0; /* Port-2, address 0A0h */
sfr P3 = 0xB0; /* Port-3, address 0B0h */
P0, P1, P2, and P3 are the SFR NAME declarations. Names for sfr variables are defined just like other C variable declarations. Any symbolic NAMEmay be used in an sfr declaration.
The address specification after the equal sign (‘=’) must be a numeric constant. Expressions with operators are not allowed. Classic 8051 devicesSUPPORT the SFR address range 0x80 to 0xFF. The PHILIPS 80C51MX provides an additional extended SFR space with the address range 0x180 to 0x1FF.
Note
sfr variables may not be declared inside a function. They must be declared outside of the function body.
COPYRIGHT (c) Keil SOFTWARE, Inc. and Keil Elektronik GmbH. All rights reserved.
sbit Types
With typical 8051 applications, it is often necessary to access individual bits within an SFR. The Cx51 Compiler makes this possible with the sbit data type which provides access to bit-addressable SFRs and other bit-addressable objects. For example:
sbit EA = 0xAF;
This declaration defines EA to be the SFR bit at address 0xAF. On the 8051, this is the enable all bit in the interrupt enable register.
Any symbolic NAME can be used in an sbit declaration. The expression to the right of the equal sign (‘=’) specifies an absolute bit address for the symbolic NAME. There are three variants for specifying the address:
Variant 1
sbit NAME = sfr-NAME ^ bit-position;
The previously declared SFR (sfr-NAME) is the base address for the sbit. It must be evenly divisible by 8. The bit-position (which must be aNUMBER from 0-7) follows the carat symbol (‘^’) and specifies the bit position to access. For example:
sfr PSW = 0xD0;
sfr IE = 0xA8;
sbit OV = PSW^2;
sbit CY = PSW^7;
sbit EA = IE^7;
Variant 2
sbit NAME = sfr-address ^ bit-position;
A CHARacter constant (sfr-address) specifies the base address for the sbit. It must be evenly divisible by 8. The bit-position (which must be aNUMBER from 0-7) follows the carat symbol (‘^’) and specifies the bit position to access. For example:
sbit OV = 0xD0^2;
sbit CY = 0xD0^7;
sbit EA = 0xA8^7;
Variant 3
sbit NAME = sbit-address;
A CHARacter constant (sbit-address) specifies the address of the sbit. It must be a VALUE from 0x80-0xFF. For example:
sbit OV = 0xD2;
sbit CY = 0xD7;
sbit EA = 0xAF;
Note
Not all SFRs are bit-addressable. ONLY those SFRs whose address is evenly divisible by 8 are bit-addressable. The lower nibble of the SFR‘s address must be 0 or 8. For example, SFRs at 0xA8 and 0xD0 are bit-addressable, whereas SFRs at 0xC7 and 0xEB are not. To calculate an SFR bit address, add the bit position to the SFR byte address. So, to access bit 6 in the SFR at 0xC8, the SFR bit address would be 0xCE (0xC8 + 6)。
Special function bits represent an independent declaration class that may not be interchangeable with other bit declarations or bit fields.
The sbit data type declaration may be used to access individual bits of variables declared with the bdata MEMORY type specifier. REFER to Bit-addressable Objects for more information.
sbit variables may not be declared inside a function. They must be declared outside of the function body.
COPYRIGHT (c) Keil SOFTWARE, Inc. and Keil Elektronik GmbH. All rights reserved.
評論
查看更多