在本文中,我们将探索如何使用8051微控制器通过串行传输发送和接收数据。那么,什么是串行传输呢?在串行传输中,数据位像这样逐位发送,以这个8位的例子来说,这个D0是最低有效位,后面跟着001001,而这个最后的D7位,也是最高有效位。为了发送这八个数据位,我们需要添加另外两个位:一个是起始位,另一个是停止位。在传输时,起始位将是第一个被传输的位,紧接着是D0,即数据的最低有效位,最后被发送的位将是停止位。

8051 串行连接
好的,在进一步讲解之前,我们再次看一下8051的模块图,

这次我将放大这个串行端口,并提取这部分在这里显示。我们关注这两个输出,或者说一个输出一个输入,即TXD和RXD。TXD,代表传输位,用于传输数据;RXD是接收数据引脚。这两个引脚负责以串行形式传输数据位。你必须记住这个串行端口和这两个位是第三端口(Port 3)的一部分。

现在,你可以通过串行端口让两个8051微控制器相互通信。我们来看这个,如果我们称这个微控制器为A,你将微控制器A的发送引脚连接到微控制器B的接收引脚上。同样,取微控制器B的发送引脚,将其连接到微控制器A的接收引脚上。通过这种方式,这两个8051可以利用串行传输进行通信。

传送和接收数据(Transmittng and Receiving)
好的,现在我们来看8051是如何串行传输和接收数据的。但在那之前,让我们回顾一下特殊功能寄存器SFRs,这是特殊功能寄存器的内存映射图。

我想请大家注意两个寄存器,第一个是串行控制寄存器SCON,地址是98H;另一个是串行缓冲寄存器S-BUFF,地址是99H。我需要指出的是,这实际上是两个独立的寄存器,我们稍后会讲到这个。
所以这里是串行部分,我们放大串行端口,让我们看看里面是什么。

这是串行端口内部的模块图表示。

在我们看这些模块之前,提醒一下,这是传输引脚,是第三部分的第1位P3.1,接收引脚P3.0,就像刚才提到的。串行缓冲(SBUFF)实际上是两个独立的寄存器,附加到接收S-BUFF寄存器的还有一个移位寄存器(Shift Register),我稍后会详细说明这个。
嗯,正如提到的,有两个S-BUFF寄存器,一个用于传输数据,这个寄存器是只读的;另一个用于接收数据,也是只读的。好的,我们来看数据是如何被传输的。要向外界传输数据,你需要在S-BUFF传输寄存器中写入或存储数据。除了你想要发送的数据之外,你还需要在数据之前添加起始位和停止位,然后才能以串行方式发送出去。

在接收端,数据通过P3.0进入,起始位和停止位被移除,输入被送入一个移位寄存器,基本上这会将其转换为并行输出,然后将接收到的数据传递给S缓冲区并存储在S缓冲区寄存器中。

波特率(Bude Rate)
现在,在继续其他内容之前,我们来定义一下波特率这个术语。波特率基本上指定或指明了数据发送和接收的速度。高波特率意味着数据被更快地发送和接收。现在,如果你要连接两个设备,例如两个8051,你必须确保这两个设备都以相同的波特率运行。也就是说,如果你想通过串行端口连接这两个设备。
基本寄存器(Basic Register)
在我们开始探讨如何为串行传输编程8051之前,让我们先看一下涉及的基本寄存器。第一个是我们之前提到过的串行缓冲寄存器或S缓冲寄存器。这是一个提醒,这是要通过TXD传输线串行传输的一个字节的数据,或者它保存了由RXD线接收的一个字节的数据。
另一个涉及的寄存器是串行控制寄存器或SCON寄存器,这是一个8位寄存器。让我们来详细看看SCON寄存器。

让我们看看位七和位六,即SM0和SM1。我之所以看这两个位,是因为SM0和SM1将决定SCON寄存器的操作模式。现在有四种可能性,但我将只看模式1。所以在模式1中,SM0是0,SM1是1,这种模式将把串行端口设置为8位UART(通用异步接收/发送器)。串行端口是一个设备,也被称为UART。所以,在模式1下,它将被配置为8位UART,由定时器1决定波特率。我们将在编程部分讲到这一点。当SCON在模式1下操作时,我们将有8个数据位、1个起始位和1个停止位。

接下来,我们来看下一个位,我不会在这里做所有的位,但我会关注与我们相关的位。下一个我想看的位是REN位,基本上,当这个位被设置为逻辑1时,它允许8051接收数据;如果设置为0,它将禁用接收器。

下一个对我们来说很重要的位是这里的TI位或传输中断位。当TI是逻辑1时,表示数据位的传输已经完成。

下一个是这里最不显著的位RI,代表接收中断。当RI是逻辑1时,基本上它告诉我们数据已经被接收。

练习:
1、使用串口传送字符H。
Mov TMOD,#20H ;Timer 1, mode 2
Mov TH1,#0FDH ;9600
Mov SCON,#50H ;8-bit, 1 stop bit, 1 start bit
Setb TR1 ;Start timer
Again: Mov SBUF,#'H' ;char "H" to be send
Here: Jnb TI, Here ;check for last char
Clr TI ;T1=0 - clear
Sjmp Again ;repeat
End
我们来看第一个指令。
MOV TMOD,#20H
这将把20H复制到TMOD寄存器中,基本上这将设置定时器1为模式2。
Mov TH1,#0FDH ;9600
然后我们将这个值FDH复制到定时器一的高字节,这将把波特率设置为9600。我稍后会解释这个值FD的细节。
Mov SCON,#50H
第三个指令将把50H复制到SCON寄存器中,这将给我们8位、1个停止位和1个起始位。
Setb TR1;Start timer
然后这个指令设置TR1位,这将启动定时器。
然后我们来看下半部分:
Mov SBUF,#'H'
将把大写字母H复制到S缓冲区寄存器中。作为一个提醒,这是因为我们想要传输这个大写字母H,所以我们需要将其存储在S缓冲区寄存器中。
Jnb TI, Here
这个指令将监控TI位或TI标志,如果它没有被设置,那么它将停留在这里。一旦它被设置,这意味着TI等于1,你将退出这个循环,下来这里
Clr TI ;T1=0 - clear
这个指令将清除TI标志,下来到这个指令,你将重复这个过程。所以,我们将在串行终端上不断显示大写字母H。
在我们继续代码演示之前,我想澄清这个指令:
MOV TMOD,#20:
基本上,这个指令利用了TMOD寄存器。快速提醒一下,TMOD寄存器是一个8位寄存器,前四位用于定时器0,上四位用于定时器1。所以这个指令将把20H复制到TMOD寄存器中,这将配置定时器1,即这里的这个定时器,为模式2操作。如果我们将这个0H转换为其二进制等价物,你将得到这个0 0 1 0,而这里零将是0 0 0 0,因为我们不使用定时器0,所以我们将把它放在一边。
现在回到这个定时器1,所以GATE是0,C/T是0,所以这是0,因为我们使用它作为定时器,GATE是0,我们使用内部时钟,M1和M0基本上决定了模式,所以M1是1,M0是一个0,因此它将给我们模式2操作。

下一个指令是将FDH复制到定时器1的高字节,这将设置波特率为9600。问题是,我们从哪里得到这个FDH呢?实际上,你可以从这个表中得到FDH,这里列出了常见的波特率和你需要复制到定时器1高字节的十六进制值。所以,在我们的例子中,9600是FD,所以我们做
MOV TH1,#FDH
这将把FDH复制到定时器1的高字节。

另一个我们关心的寄存器是SCON寄存器,我们把50H这个值复制到SCON寄存器中,这将把它配置为8位、1个停止位和1个起始位。所以50H转换为二进制将是这个,而SM0SM1将把它配置为8位、1个停止位和1个起始位操作。现在REN位在这里,一个1将启用数据库的接收,0在这里将禁用接收。所以,因为我们想要接收,我们需要把这个设置为1。

在模拟器中运行程序可以看见Rx窗口接收到字符H,注意要将程序中波特率改为4800:
