UART-通用异步收发器
UART-通用异步收发器
数字系统是以0或1的形式分享和存储信息。不同结构的设备相互访问,需要一种通用的数据交换方法。这就是各种通信协议发挥作用的地方,其中之一就是通用异步收发器(UART)。它是嵌入式电子设备中使用最广泛的通信协议。它是一种串行,全双工,异步,板对板的通信协议。在弄懂协议之前,先明确几个关键词。
l 串行通信:对于串行通信,只需要一个或两个连接来发送或接收数据。数据的发送和接收每次一位,顺序完成。
l 并行通信:对于并行通信,有多条线路用于数据传送。线路的数量被称为总线的宽度。下图可以看出是一个8位总线,一次传送8位数据。

图1. 并行通信和串行通信对比
l 异步通信:在异步通信中,设备不共享一个公共时钟来同步数据传输。相反,它们同意相同的传输速率,在设备内部配置时钟来捕获或传输数据。
l 全双工通信:在全双工通信中,存在单独的线路同时进行发送和接收。
如下图所示,设备同时发送和接收数据。

图2 全双工通信
现在,我们已经了解了一些术语和基本概念,可以继续去弄明白UART是如何工作的。
UART说明
UART作为全双工异步通信协议,发送和接收数据可以同时发生。因此,要区分发送和接收数据的引脚。TX发送数据,RX接收数据。设备之间的发送和接送引脚交叉连接,如下图所示。

图3. UART全双工通信连接
注意接地。完成硬件连接后,接下来搞清楚UART的数据包。

图4 UART数据帧
1. 同步位
起始位1位,结束位1~2位。它们表示数据包的开始和结束。当开始传输时,线路被拉低。表示开始启动传输,然后又被拉高,表示传输结束。当线路是高电平状态时,表示空闲或没有数据在传输。起始位是1位,结束位可以是1位,也可以是2位。对于某些微处理器,比如STM32F4系列,结束位也可以配置成1.5位。

图5 UART数据包的启动和结束位
2. 数据位
数据帧的这部分是核心,它携带着要发送给接收端的数据。这个块的长度5位到9位不等,取决于设备间的协议配置。标准的数据大小是8位或1个字节。根据UART标准,该协议遵循小端顺序,数据发送从最低有效位到最高有效位,也可以配置成大端序,从最高有效位到最低有效位。

图6 UART大端序传送
3. 检验位
UART带有错位检查机制,检查接收到的数据完整性。数据是按字节发送的,错误检查也是逐个字节完成。它使用校验位来做这一点,它在数据位后,发送错误码。校验位有两种模式:奇校验或偶校验。
奇校验:为了检测数据完整性,程序将检测数据中1的数量,包含校验位。发送器执行以下步骤为数据帧生成校验位。
- 计算数据位里1的个数。
- 如果1的个数是奇数,就把校验位设置为0,反之,设置为1.这样就保证了数据位+校验位里整体1的个数是奇数。
- 接收端收到数据后,检查1的个数,如果是奇数个,就是有效的数据,反之,就是无效的数据。
偶校验:与奇校验类似,检查1的个数是不是偶数个(包含校验位),接收端也同样检查。
这是一种简单的错误检查机制,但是如果多位数据错误,就无法判断接收的数据哪一位是否出错。
接下来我们研究UART在没有公共时钟的情况下如何同步传输数据,它是靠波特率配置来实现。
4. 波特率
它指定数据发送的速度,单位是bps(比特/秒)。在UART通信时,设备使用同一个波特率。标准的波特率有9600,38400,115200,921600等。对波特率取倒数,就能得到发送1位数据需要的时间。比如:

因此,使用9600的波特率,传输1位的时间时104.16微秒。对于硬件,线路将被设备拉高或拉低104.16微秒。
现在,你几乎了解了所有实现协议需要的内容。这些知识在调试程序时非常重要。既然已经完成理论部分,接下来开始实践吧。
UART实践
为了方便,我们使用Arduino UNO与PC通信。串口通信显示“Hello World”。计算机没有用于UART的外部端口,通信用USB到UART转换器。如果没有相关硬件,也可以使用在线的仿真((Wokwi, Tinkercad)。
根据Arduino的文档,串口0用来与PC通信,

图7 Auduino上的串口0
首先,需要设定波特率。这里使用9600bps。默认情况下,Auduino UNO使用8-N-1数据帧,8位数据,没有校验位,1位停止位。下面的代码执行发送“Hello World”到PC。
void setup() {
// the baud rate is set to 9600 bps
Serial.begin(9600);
}
void loop() {
// a string is transmitted over Serial0
Serial.println("Hello World");
// standby for 50 ms
delay(50);
}
将上述代码复制到Arduino IDE,在Tools里选择板和端口,把代码上传到板,就可以看到显示的字符。

图8-1 选择板

图8-2 选择端口

图8-3 串口监视器输出

图8-4 Arduino UNO和PC连接
如果你在屏幕上看到了“Hello Wworld”,表示操作成功,反之,再试一次。
我们接下来一步步分析,字符串是如何传送到串行监视器的。在Arduino后台,把字符串“Hello World”后面加上换行符\n,所以要传送的数据实际是12个,并转换成ASCII形式,因此,需要12个数据帧来完成这个字符串的传送。
第一个发送的字符是H,ASCII是104.对应的二进制值是01101000.这里的0和1表示UART数据帧的数据位。起始的0和结尾的1表示数据帧的开始和结束。

图9 UART传送’H’的数据帧
H传送完成后,接着传送e,依此类推,一个接一个传送。
下面是所有字符传送的演示。

图10 字符串发送演示
现在,明白了为何UART会成为通信协议的首先,因为简单,易于设置。但是这种简单也是有代价的:
- 它只支持两个设备间的通信,不能在同一条线上有多个设备。
- UART虽然支持较快的波特率,比如921000,但它相对其他协议,比如SPI,I2C,还是慢一些。
即便有这些缺点,UART还是传感器和智能电机驱动厂商的首先,因为接口简单,不用考虑用户使用的微控制器的结构。比如激光雷达测距,通过UART读取测得的距离数据。3D打印机的串口有特殊的数据包,用于执行安装调试;同样,我们也可以用简单而健壮的通信协议比如UART去构建复杂的工具和接口。
参考:https://www.circuitbread.com/tutorials/uart-universal-asynchronous-receiver-transmitter
浙公网安备 33010602011771号