如 sfr SBUF = 0x99;当然你也能用其它的名称。通常在标准的 reg51.h 或 at89x51.h 等 头文件中已对其做了定义,只要用#include 引用就能了。
SCON 串行口控制寄存器 通常在芯片或设备中为了监视或控制接口状态,都会引用 到接口控制寄存器。SCON 就是 51 芯片的串行口控制寄存器。它的寻址地址是 98H,是一个 能位寻址的寄存器,作用就是监视和控制 51 芯片串行口的工作状态。51 芯片的串行口能 工作在几个不一样的工作模式下,其工作模式的设置就是使用 SCON 寄存器。它的各个位的具 体定义如下:
SM0、SM1 为串行口工作模式设置位,这样两位能对应进行四种模式的设置。看表 8-2 串行口工作模式设置。
SM0
SM1
模 式
功 能
波特率
0
0
0
同步移位寄存器
fosc/12
0
1
1
8 位 UART
可变
1
0
2
9 位 UART
fosc/32 或 fosc/64
1
1
3
9 位 UART
可变
表 8-2 串行口工作模式设置
在这里只说明最常用的模式 1,其它的模式也就一一略过,有兴趣的朋友能找相关的 硬件资料查看。表中的 fosc 代表振荡器的频率,也就是晶体震荡器的频率。UART 为(Universal Asynchronous Receiver)的英文缩写。
SM2 在模式 2、模式 3 中为多处理机通信使能位。在模式 0 中要求该位为 0。
REM 为允许接收位,REM 置 1 时串行口允许接收,置 0 时禁止接收。REM 是由软件置位或 清零。如果在一个电路中接收和发送引脚 P3.0,P3.1 都和上位机相连,在软件上有串行口中断 处理程序,当要求在处理某个子程序时不允许串行口被上位机来的控制字符产生中断,那么可 以在这个子程序的开始处加入 REM=0 来禁止接收,在子程序结束处加入 REM=1 再次打开串行口 接收。大家也能用上面的实际源码加入 REM=0 来进行实验。
TB8 发送数据位 8,在模式 2 和 3 是要发送的第 9 位。该位能用软件根据需要置位或 清除,通常这位在通信协议中做奇偶位,在多处理机通信中这一位则用于表示是地址帧还是 数据帧。
RB8 接收数据位 8,在模式 2 和 3 是已接收数据的第 9 位。该位可能是奇偶位,地址/ 数据标识位。在模式 0 中,RB8 为保留位没有被使用。在模式 1 中,当 SM2=0,RB8 是已接 收数据的停止位。
TI 发送中断标识位。在模式 0,发送完第 8 位数据时,由硬件置位。其它模式中则是在 发送停止位之初,由硬件置位。TI 置位后,申请中断,CPU 响应中断后,发送下一帧数据。 在任何模式下,TI 都必须由软件来清除,也就是说在数据写入到 SBUF 后,硬件发送数据,
中断响应(如中断打开),这个时候 TI=1,表明发送已完成,TI 不会由硬件清除,所以这个时候必须用软件对其清零。
RI 接收中断标识位。在模式 0,接收第 8 位结束时,由硬件置位。其它模式中则是在接 收停止位的半中间,由硬件置位。RI=1,申请中断,要求 CPU 取走数据。但在模式 1 中,SM2=1 时,当未收到有效的停止位,则不会对 RI 置位。同样 RI 也必须要靠软件清除。
常用的串行口模式 1 是传输 10 个位的,1 位起始位为 0,8 位数据位,低位在先,1 位停止 位为 1。它的波特率是可变的,其速率是取决于定时器 1 或定时器 2 的定时值(溢出速率)。 AT89c51 和 AT89C2051 等 51 系列芯片只有两个定时器,定时器 0 和定时器 1,而定时器 2是 89C52 系列芯片才有的。
波特率 在使用串行口做通信时,一个很重要的参数就是波特率,只有上下位机的波特率 一样时才能进行正常通信。波特率是指串行端口每秒内能传输的波特位数。有一些开始学习 的朋友认为波特率是指每秒传输的字节数,如标准 9600 会被误认为每秒种能传送 9600 个字节,而实际上它是指每秒能传送 9600 个二进位,而一个字节要 8 个二进位,如用串 口模式 1 来传输那么加上起始位和停止位,每个数据字节就要占用 10 个二进位,9600 波特 率用模式 1 传输时,每秒传输的字节数是 9600÷10=960 字节。51 芯片的串行口工作模式 0 的波特率是固定的,为 fosc/12,以一个 12M 的晶体震荡器来计算,那么它的波特率能达到 1M。 模式 2 的波特率是固定在 fosc/64 或 fosc/32,具体用那一种就取决于 PCON 寄存器中的 SMOD 位,如 SMOD 为 0,波特率为 focs/64,SMOD 为 1,波特率为 focs/32。模式 1 和模式 3 的波 特率是可变的,取决于定时器 1 或 2(52 芯片)的溢出速率。那么我们怎么去计算这两个模 式的波特率设置时相关的寄存器的值呢?能用以下的公式去计算。
波特率=(2SMOD÷32)×定时器 1 溢出速率
上式中如设置了 PCON 寄存器中的 SMOD 位为 1 时就能把波特率提升 2 倍。通常会使用 定时器 1 工作在定时器工作模式 2 下,这个时候定时值中的 TL1 做为计数,TH1 做为自动重装值 , 这个定时模式下,定时器溢出后,TH1 的值会自动装载到 TL1,再次开始计数,这样能不 用软件去干预,使得定时更准确。在这个定时模式 2 下定时器 1 溢出速率的计算公式如下:
溢出速率=(计数速率)/(256-TH1) 上式中的“计数速率”与所使用的晶体振荡器频率有关,在 51 芯片中定时器启动后会
在每一个机器周期使定时寄存器 TH 的值增加一,一个机器周期等于十二个振荡周期,所以
能得知 51 芯片的计数速率为晶体振荡器频率的 1/12,一个 12M 的晶体震荡器用在 51 芯片上, 那么 51 的计数速率就为 1M。通常用 11.0592M 晶体是为了得到标准的无误差的波特率,那 么为何呢?计算一下就知道了。如我们要得到 9600 的波特率,晶体震荡器为 11.0592M 和 12M,定 时器 1 为模式 2,SMOD 设为 1,分别看看那所要求的 TH1 为何值。代入公式:
11.0592M
9600=(2÷32)×((11.0592M/12)/(256-TH1))
TH1=250 //看看是不是和上面实例中的使用的数值一样?
12M
9600=(2÷32)×((12M/12)/(256-TH1)) TH1≈249.49
上面的计算能看出使用 12M 晶体的时候计算出来的 TH1 不为整数,而 TH1 的值只能取整数,这样它就会有一定的误差存在不能产生精确的 9600 波特率。当然一定的误差是能 在使用中被接受的,就算使用 11.0592M 的晶体振荡器也会因晶体本身所存在的误差使波特率产生误差,但晶体本身的误差对波特率的影响是十分之小的,能忽略不计。