购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.3 特殊功能寄存器

由图1-3可知,片内数据RAM中80H~FFH空间大部用于特殊功能寄存器,表1-1列出了8051单片机的所有特殊功能寄存器。

表1-1 8051单片机的特殊功能寄存器

上述特殊功能寄存器分别用于以下功能单元。

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语言程序时将被大量使用。对于可位寻址的SFR,例如,ACC寄存器,它常被用于判断字节中各位的状态,要判断某字节第3位是否为1,可将ACC看成1字节变量,ACC获取该字节的值后可直接判断ACC3是否为1,当然需要先有定义sbit ACC3 = ACC^3。

又如,程序状态字(Program Status Word,PSW)寄存器,头文件reg51.h已包含了该寄存器的各位定义,其部分内容如下:

PSW寄存器中的CY和F0在C语言程序中仍然被直接大量使用,如要将字节变量d(假定为10101101)由高位开始逐位串行发送,可对d进行8次左移,并逐次发送CY,即

代码中DQ为某外部芯片读/写串行数据的引脚定义,这段代码利用汇编语言程序中常用的进位标志位CY,可以方便地获取移出的各位。

表1-1中带有*号的特殊功能寄存器是可位寻址的,Keil\C51下头文件reg51.h对P0~P3以外的可位寻址的各寄存器位给出了独立定义,如果要直接引用4个I/O端口的各引脚,需要在程序中用sbit进行单独定义,当然也可以将头文件reg51.h(keil\c51\inc)改成at89x52.h(keil\c51\inc\atmel),4个接口的各引脚在该头文件中均被单独定义,如P0.1被定义为P0_1,尽管其中有些定义对8051单片机是无效的,但这并不影响程序正常编译运行。

1.1节“8051单片机引脚”曾提到端口结构中的“读锁存器”与“读引脚”的问题,这些问题的解释涉及8051单片机的相关特殊功能寄存器。此前已经提到,凡“读-改-写”这类指令,CPU将执行“读锁存器”,否则将为“读引脚”,下面通过实例说明这一问题。

以汇编指令ORL P2, A为例,它相当于C语言的P2 = P2 | ACC或P2 |= ACC,现假设在P2.0引脚接有一开关,执行程序之前先合上开关使P2.0引脚接地,然后依次执行:

其中最后的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接地,依次执行下述语句:

观察单片机P2端口,可知其状态为0x76,且断开开关后仍为0x76,可见对于ACC = P2,CPU控制执行的是“读P2引脚”上的0x32,而不是“读P2锁存器”中的0x33。

在所设计的单片机系统中,如果接口输出值可能被外部改变,而程序要求每次均在上次输出值的基础上运算处理后输出,而不是在输出发生变化值的基础上运算处理再输出,这时就要考虑到所编写的C程序生成的指令是“读-改-写”类指令,还是仅为“读”类指令。

具体生成为何类指令,需要通过Keil µVision的反编译功能查看,而不能凭直觉判断。例如:

P2 = P2 | i 反编译后的汇编指令如下,其中0x08为编译器分配给变量i的地址:

显然,由于编译生成了“读-改-写”类指令“ORL P2, A”,故CPU处理该语句时将执行“读锁存器”操作而不是“读引脚”操作。

再如P2 =(P2 & 0xF8)| i,其反编译后的汇编指令如下,其中0x08仍为变量i的地址:

可见,CPU处理该语句时执行的将是“读引脚”而不读“读锁存”操作。

对于P0~P3端口的“读”/“写”操作还应注意,由于初始上电时它们全部被写入“1”,故可以不需要任何初始化而直接读取端口外部数据。但如果端口曾输出过“0”,之后又需要逆向读入外部数据,此时则需要在相应端口位上先输出“1”,1.1节“8051单片机引脚”已经讨论过这样操作的原理。 kW8mJOzLu6IcAhKC60DDVrJCIZfDXIj7Qq3RBQQattVLVlrB202Lpp3yClzlYx4N

点击中间区域
呼出菜单
上一章
目录
下一章
×