![单片机C语言程序设计实训100例:基于STC8051+Proteus仿真与实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/270/43738270/b_43738270.jpg)
1.4 特殊功能寄存器
8051单片机特殊功能寄存器如表1-3所示。其中,片内RAM 80H~FFH单元大部分被用于特殊功能寄存器。
表1-3 8051单片机特殊功能寄存器
![](https://epubservercos.yuewen.com/DF9E4A/23020648309755406/epubprivate/OEBPS/Images/42553-00-20-3.jpg?sign=1739306661-juj5q67wNuQ00c0RWocHGb410jmypHXW-0-75ad240ef0c9d72301cdfe14e59f1c3f)
注:带有*号的特殊功能寄存器是可位寻址的。
上述特殊功能寄存器分别被用于以下功能单元。
CPU:ACC、B、PSW、SP、DPTR。
并行端口:P0、P1、P2、P3。
中断系统:IE、IP。
定时/计数器模块:TMOD、TCON、T0(TH0、TL0)、T1(TH1、TL1)。其中,TCON还含有外部中断标志位及外部中断触发方式配置位。
串行通信模块:SCON、SBUF、PCON。
这些特殊功能寄存器在开发单片机C语言程序时将被大量使用。对于可位寻址的特殊功能寄存器,例如,ACC寄存器常被用于判断字节中各位的状态。如果要判断某字节第3位是否为1,可将ACC寄存器看成一个字节变量,ACC寄存器获取该字节值后即可直接判断ACC3是否为1,前提是要先定义sbit ACC3=ACC^3。
又如程序状态字(Program Status Word,PSW)寄存器,在Keil\C51下的头文件reg51.h中包含有该寄存器的各位定义,其部分内容如下:
![](https://epubservercos.yuewen.com/DF9E4A/23020648309755406/epubprivate/OEBPS/Images/42553-00-21-1.jpg?sign=1739306661-w0xsCsoIDZ3SmeAjlKjSloajAAppJFmO-0-a4d701a7b7f81c487b4ab436c95fba21)
PSW寄存器中的CY和F0在C语言程序中仍然被直接大量使用,如要将字节变量d(假定为10101101)由高位开始逐位串行发送,可对d进行8次左移,并逐次发送CY,即
![](https://epubservercos.yuewen.com/DF9E4A/23020648309755406/epubprivate/OEBPS/Images/42553-00-22-1.jpg?sign=1739306661-rwUsNgLwVV77aNnX4YcGnBsuQSrewCU6-0-b69c7690ea7779ada4ee13d4b28a27f9)
其中,DQ被定义为某外部芯片读/写串行数据的引脚。这段代码利用了汇编语言程序中常用的进位标志位CY,可方便地获取移出的各位数据。
该头文件对P0~P3以外可位寻址寄存器位给出了独立定义,如果要直接引用4个I/O端口各引脚,要在程序中用sbit进行单独定义。当然也可将头文件reg51.h(keil\c51\inc)改成at89x52.h(keil\c51\inc\atmel),4个I/O端口各引脚在该头文件中均被单独定义,如P0.1被定义为P0_1。尽管其中有些定义对8051单片机是无效的,但这并不影响程序的正常编译运行。
此前曾提到I/O接口位结构中的“读锁存器”与“读引脚”的问题,这些问题的解释涉及8051单片机的相关特殊功能寄存器。凡是“读—改—写”这类指令,CPU将执行“读锁存器”,否则CPU将执行“读引脚”。下面通过实例说明这一问题。
以汇编指令ORL P2, A为例,它相当于C语言的P2=P2|ACC或P2|=ACC指令。现假设在P2.0引脚接有一个开关,执行程序之前先合上该开关使P2.0引脚接地,然后依次执行:
![](https://epubservercos.yuewen.com/DF9E4A/23020648309755406/epubprivate/OEBPS/Images/42553-00-22-2.jpg?sign=1739306661-hL2ByC5ISsl7rA8EnYIGiiIkxOyTYmbY-0-d770ffb05867f6f26c4ab658fe528eac)
其中,最后的while(1)相当于汇编语言指令JMP $,它使程序执行到该位置后进入死循环,以便观察单片机接口状态。上述语句执行后,P2引脚输出应为0x77(0111 0111)还是0x76(0111 0110)呢?
实际情况是,如果开关仍然是合上的,通过Proteus仿真软件可观察到P2引脚状态为0x76;如果开关是断开的,则P2引脚状态变为0x77。显然,对于P2=P2|ACC这样的“读—改—写”指令,CPU执行的是“读锁存器”。这是因为如果是“读引脚”,则所读取的P2将为0x32而不是0x33,最终结果将为0x76而不会在断开开关时变为0x77。
可见,CPU执行的是“读锁存器”而非“读引脚”,这样可避免此前输出到“引脚”的值可能被外部改变的情况。“读锁存器”可确保读取的是此前输出的原始值,而不是输出后被外部改变过的值。
又如,指令MOV A, P1,相当于C语言的ACC=P1,CPU显然将发出“读引脚”信号。仍假设运行程序之前开关是合上的,P2.0接地,依次执行下述语句:
![](https://epubservercos.yuewen.com/DF9E4A/23020648309755406/epubprivate/OEBPS/Images/42553-00-22-3.jpg?sign=1739306661-FhpMOtsCb6uqjz8uqJR7QnItjTP0k69H-0-8359d4bbc3f6a0aabe3f44b69540c871)
观察单片机P2引脚,可知其状态为0x76,且断开开关后仍为0x76。可见,对于ACC=P2,CPU执行的是“读P2引脚”上的0x32,而不是“读P2锁存器”中的0x33。
对于P0~P3端口的“读/写”操作还应注意,由于初始上电时它们全部被写入“1”,故可以不用初始化它们而直接读取它们的外部数据。但如果它们曾输出过“0”,之后又要逆向读入外部数据,此时则要在相应端口位上先输出“1”。
STC15特殊功能寄存器与高128B RAM共用相同的地址,都使用80H~FFH。访问特殊功能寄存器必须用直接寻址指令。STC15系列单片机特殊功能寄存器如表1-4所示。由表1-4可知,相较于传统型8051单片机,STC15特殊功能寄存器被大量扩充,这也意味着其功能相较于传统8051单片机有了显著增强。
表1-4 STC15系列单片机特殊功能寄存器
![](https://epubservercos.yuewen.com/DF9E4A/23020648309755406/epubprivate/OEBPS/Images/42553-00-23-1.jpg?sign=1739306661-4M6Kc94i5crqcCXQGJ00R0qiQeKdOOha-0-ea808439448fa8d383276e52be179e46)
续表
![](https://epubservercos.yuewen.com/DF9E4A/23020648309755406/epubprivate/OEBPS/Images/42553-00-24-1.jpg?sign=1739306661-oxVsRN3J7GNOesbCuVrmqIS7erGRRGUo-0-ab7c728a188805e7531803b247f4ad54)
续表
![](https://epubservercos.yuewen.com/DF9E4A/23020648309755406/epubprivate/OEBPS/Images/42553-00-25-1.jpg?sign=1739306661-kbobajnZjcBcHW9w3L340nbJz8Rdc5z3-0-593847396ab898e0319234586354c3e1)
续表
![](https://epubservercos.yuewen.com/DF9E4A/23020648309755406/epubprivate/OEBPS/Images/42553-00-26-1.jpg?sign=1739306661-fUDg1ge3i4FpNPHs2ElLhwBh96wmwvpp-0-c94b475ea3dbd3203cdf6f8175c1239d)
续表
![](https://epubservercos.yuewen.com/DF9E4A/23020648309755406/epubprivate/OEBPS/Images/42553-00-27-1.jpg?sign=1739306661-F2mrAIW3HmGwqcS2pGGr0sTLAhjZB992-0-c8992617e63e902a2daaa306f626ce64)
续表
![](https://epubservercos.yuewen.com/DF9E4A/23020648309755406/epubprivate/OEBPS/Images/42553-00-28-1.jpg?sign=1739306661-S02cRAT2IuKUynC4s1MhMixMkyZdNqLR-0-5f5ef182a59ea1a964164361a937893a)
注:串口为串行接口的简称。