1. UART通信基础与流控制机制详解
在嵌入式开发和工业控制领域,UART(通用异步收发传输器)几乎是工程师最常打交道的通信接口之一。它结构简单,无需时钟线,仅凭两根数据线(TxD和RxD)就能实现全双工通信,这使得它在调试、日志输出、设备间数据交换等场景中无处不在。但“简单”往往意味着细节决定成败,尤其是在高速或长距离通信时,数据丢失、错位等问题会频繁出现。这时,硬件流控制(Hardware Flow Control)就从一个“锦上添花”的功能变成了“雪中送炭”的必需品。
硬件流控制的核心思想,是让接收方有能力告诉发送方:“我忙不过来了,请暂停发送”。这就像两个人对话,当一方说话太快时,另一方可以举手示意“请慢一点”。在UART中,这个“举手”的动作就是通过RTS(Request To Send,请求发送)和CTS(Clear To Send,清除发送)这两根额外的信号线完成的。RTS是接收方输出的信号,表示“我准备好接收了”;CTS是发送方输入的信号,表示“允许我发送”。当接收方的缓冲区(通常是FIFO)快满时,它会拉低RTS信号(即否定RTS),发送方检测到CTS为低后,便会暂停发送,直到接收方处理完部分数据,缓冲区有空位,再重新拉高RTS,发送方检测到CTS变高后继续发送。
以SCF5250的UART模块为例,其流控制机制设计得非常智能。接收器可以被编程为自动控制RTS信号。当检测到一个有效的起始位,且接收FIFO已满时,接收器会自动否定(拉低)RTS。一旦FIFO中有一个位置变得可用,接收器会立即断言(拉高)RTS。这种自动化的“握手”过程,从根本上避免了因接收方处理不及时而导致的过载错误(Overrun Error)。过载错误是指新的字符已经到达并进入了移位寄存器,但前一个字符还未从FIFO中读出,导致新字符被覆盖丢失。这是异步通信中最令人头疼的错误之一,因为它是静默发生的,没有奇偶校验或帧错误那样的直接标志,只能通过数据丢失或校验和不匹配来间接发现。
注意:要实现RTS/CTS流控制,必须正确连接硬件。通常是将设备A的RTS输出连接到设备B的CTS输入,同时将设备B的RTS输出连接到设备A的CTS输入,形成交叉互联。如果只连接单向,则只能实现单方面的流量控制。
1.1 SCF5250 UART流控制配置实操
要让SCF5250的UART1支持RTS自动流控制,需要进行一系列寄存器配置。首先,你需要确保对应的I/O引脚功能被正确启用。这需要通过系统集成模块(SIM)中的引脚配置寄存器来完成。假设我们使用UART1,需要找到对应的引脚复用控制位,将其设置为UART功能,而非普通的GPIO。
配置好引脚后,核心在于设置模式寄存器1(UMR1)。UMR1的Bit 7是RxRTS位,正是它控制着接收器是否自动管理RTS信号。
- 当
RxRTS = 1时:启用自动RTS控制。接收器会在FIFO满时自动否定RTS,有空位时断言RTS。 - 当
RxRTS = 0时:禁用自动控制。此时RTS的状态需要通过手动写输出端口置位寄存器(UOP1)来控制。
这里有一个非常重要的实操心得:在启用自动RTS控制前,务必先通过命令寄存器(UCR)发送一个“复位接收器(Reset Receiver)”命令。这个操作会将接收器置于一个已知的干净状态,清空FIFO指针和状态位。如果你在接收器运行时直接更改RxRTS配置,可能会因为状态机混乱导致RTS信号行为异常,比如该拉低的时候不拉低,直接引发数据溢出。
另一个容易踩坑的点是FIFO的状态读取。即使接收器被禁用(Disabled),只要FIFO里还有未读出的字符,CPU仍然可以读取它们。但是,一旦你通过“复位接收器”命令或硬件复位对整个接收器进行了复位,那么FIFO、所有接收状态位、对应的输出端口以及中断请求都会被清零。这意味着,任何残留在FIFO中的数据都将永久丢失,且在新的接收使能命令发出前,接收器不会再接收任何新字符。因此,在系统初始化或模式切换时,一定要规划好数据清空和状态迁移的顺序。
1.2 发送器侧的CTS流控制
流控制是双向的。接收方用RTS控制对方,发送方则需要监听对方的CTS来决定是否发送。在SCF5250中,这通过模式寄存器2(UMR2)的TxCTS位来控制。
- 当
TxCTS = 1时:启用CTS流控制。发送器在每次准备发送一个字符前,都会检查CTS引脚的状态。只有CTS被断言(通常为低电平有效,具体看硬件设计)时,它才会发送字符。如果CTS被否定,发送器的TxD引脚将保持高电平(标记状态),传输被延迟,直到CTS再次被断言。 - 当
TxCTS = 0时:CTS状态不影响发送器。
这里有一个关键细节:CTS状态只在字符发送开始的时刻被采样。一旦一个字符的发送已经开始,即使CTS信号在字符传输中途发生变化,也不会影响当前字符的传输。这保证了字符传输的原子性,不会出现半个字符被发送出去的情况。
重要提示:一个常见的错误配置是,在同一通道(比如UART1)上,同时为接收器和发送器启用RTS控制(即设置
RxRTS=1且TxRTS=1)。SCF5250手册明确指出,这种配置是不被允许的,并且会导致双方的RTS控制功能都被禁用。正确的做法是,在点对点全双工流控制中,设备A的接收器控制其RTS输出(连接到B的CTS),设备A的发送器监听自己的CTS输入(来自B的RTS)。TxRTS位有另一个用途,它用于在消息传输完成后自动否定RTS以终止传输,常用于半双工RS-485网络中。
2. UART循环模式:从诊断到自检的三种利器
在通信系统开发中,尤其是硬件驱动和底层协议栈调试阶段,如何快速、准确地定位问题是收发器坏了,还是软件配置错了,亦或是线路有问题?UART提供的循环模式(Looping Modes)就是为此而生的强大诊断工具。SCF5250支持三种循环模式:自动回波(Automatic Echo)、本地环回(Local Loopback)和远程环回(Remote Loopback)。它们从不同层面隔离了问题域,是硬件工程师和嵌入式软件工程师的“听诊器”。
2.1 自动回波模式(Automatic Echo Mode)
想象一下,你对着山谷大喊,然后立刻听到自己的回声。自动回波模式就类似于此,但它是在比特级别实时进行的。在此模式下,UART会自动将接收到的数据,按比特逐个重新发送到TxD引脚上。
它是如何工作的?
- 接收器必须启用,发送器必须禁用。这听起来有点反直觉,但逻辑是:数据流由外部设备输入到RxD。
- 发送器时钟由接收器时钟驱动。这意味着回波的时序完全由输入信号的时钟决定,保证了比特宽度的精确复现。
- CPU到接收器的通信正常,CPU可以读取到回波的数据。但CPU到发送器的链路被禁用,你无法通过软件主动发送数据。
关键特性与注意事项:
- 状态位无效:因为发送器未被真正激活,所以状态寄存器(USR)中的
TxEMP(发送器空)和TxRDY(发送器就绪)位是无效的。 - 校验与帧检查:接收端会进行奇偶校验和帧错误检查,但这些检查结果不会用于重新计算发送端的校验位。发送端只是原样转发接收到的校验位和停止位。
- Break信号处理:如果接收到一个Break信号(RxD被持续拉低超过一个字符时间),这个Break也会被原样回波出去,直到检测到下一个有效的起始位。
应用场景:此模式主要用于测试本设备接收通路和对方设备发送通路是否完好。你可以让另一个设备发送特定数据序列,然后观察本设备TxD引脚上的信号是否与输入一致。用逻辑分析仪或示波器同时抓取RxD和TxD信号,可以非常直观地看到延迟和信号完整性。
2.2 本地环回模式(Local Loopback Mode)
如果说自动回波是测试外部环回,那么本地环回就是彻底的“自检”。在此模式下,芯片内部将发送器的输出(TxD)直接短接到接收器的输入(RxD),形成一个内部的闭环。外部RxD引脚输入的信号被完全忽略,外部TxD引脚则保持在高电平(标记状态)。
它是如何工作的?
- 发送器必须启用,接收器必须禁用。数据流由CPU主动产生。
- 接收器时钟由发送器时钟驱动。这样确保了内部环路的时序一致性。
- CPU可以正常写入发送缓冲区,数据经过内部环路后,会被接收逻辑捕获,CPU再从接收缓冲区读出。
应用场景:这是验证UART模块自身功能是否正常的终极手段。你可以编写一个测试程序:发送一组已知的数据(例如0x55, 0xAA,这两种数据位跳变多,容易测试),然后立即从接收缓冲区读取。如果读出的数据与发送的一致,且没有产生帧错误、奇偶错误等,就基本证明从CPU总线接口、发送缓冲区、发送移位寄存器、内部环路、接收移位寄存器到接收缓冲区这一整条通路是完好的。这在你更换芯片、或怀疑UART硬件故障时非常有用。
2.3 远程环回模式(Remote Loopback Mode)
这个模式可以看作是自动回波和本地环回的混合体,主要用于测试远程设备。在此模式下,通道自动将接收到的数据按比特发送到TxD输出,同时禁用本地CPU到发送器的链路。
它是如何工作的?
- 接收器必须启用,以提供时钟和数据。发送器也被使用,但其数据源不是CPU,而是接收到的比特流。
- 接收器时钟驱动发送器。
- CPU无法读取接收到的数据,因为接收器逻辑虽然在工作,但并不将数据存入供CPU读取的缓冲区。所有的状态条件(如RxRDY)也都是无效的。
应用场景:假设你有设备A和设备B通过串口相连。你可以在设备A上启用远程环回模式,然后从设备B向设备A发送数据。如果设备B能收到自己发送的数据,那就证明从设备B的TxD到设备A的RxD,再到设备A的TxD,最后回到设备B的RxD这整个物理链路是通畅的。这常用于在现场排查线缆故障或远程设备接口故障。
模式切换的黄金法则:手册中特别强调,切换循环模式必须在发送器和接收器都被禁用的情况下进行。因为模式选择是立即生效的,哪怕切换发生在字符传输或接收的中间时刻。这种突然的切换会导致不可预知的结果,比如数据错位或状态机死锁。唯一的例外是自动回波和远程环回模式,当从中退出时,退出动作会延迟到接收器采样完停止位的中间点(即1.5个比特时间点)后才发生,这给了当前字符一个完成的时机。
3. 多机通信模式:构建主从网络的基石
在工业控制、传感器网络等场景中,经常需要一个主机与多个从机通信。如果每个从机都独占一对UART,主机的UART资源将很快耗尽。UART的多机模式(Multidrop Mode,也叫多处理器模式)就是为了解决这个问题,它允许单个主机UART通过一条总线与最多256个从机通信。
3.1 多机通信的工作原理
多机通信的核心思想是“地址唤醒”。在普通模式下,所有数据都被视为有效数据。而在多机模式下,数据流被分为两种类型的字符:地址字符和数据字符。每个字符中除了常规的起始位、数据位、停止位,还包含一个特殊的地址/数据标识位。
- 初始状态:所有从机的接收器都处于“禁用但监听”状态。它们不将数据存入CPU可读的缓冲区,但会持续监视总线上的数据流。
- 主机寻址:当主机需要与某个从机通信时,它先发送一个地址字符。这个字符的A/D位被设置为1(表示这是一个地址)。
- 从机响应:所有从机在收到这个地址字符后,都会产生中断(如果已使能),并将地址字符加载到它们的接收缓冲区(尽管接收器是“禁用”的,但地址字符是例外)。每个从机的CPU读取这个地址,并与自己预设的站地址进行比较。
- 目标从机激活:地址匹配的那个从机,会通过软件启用(Enable)自己的接收器。此时,它便能够接收后续的数据字符。
- 数据传输:主机开始发送数据字符流。这些字符的A/D位被设置为0。只有那个启用了接收器的目标从机能将这些数据字符存入缓冲区并交给CPU处理。其他从机则直接丢弃这些A/D位为0的字符。
- 通信结束:数据块发送完毕后,主机可以发送下一个地址字符,与另一个从机通信。之前的目标从机在接收完数据后,应通过软件再次禁用自己的接收器,重新回到监听状态,等待下一次被寻址。
这种机制极大地节省了总线资源,并且从机只有在被寻址时才消耗CPU资源处理数据,实现了简单的网络管理。
3.2 SCF5250多机模式的配置与细节
在SCF5250上启用多机模式,需要通过模式寄存器1(UMR1)的PM1和PM0位来设置。当PM1:PM0 = 11时,即选择了多机模式。此时,PT(奇偶校验类型)位的作用发生了变化:它用于配置发送器发送的是地址字符(PT=1)还是数据字符(PT=0)。
几个需要特别注意的寄存器行为变化:
状态寄存器(USR)中的PE位:在普通模式下,
PE位表示奇偶校验错误。但在多机模式下,PE位被用来存储接收到的A/D位。也就是说,当你从接收缓冲区读取一个字符时,需要同时检查数据位和这个“伪”奇偶错误位,来判断收到的是地址还是数据。因此,在多机模式下,必须将UMR1中的ERR位设置为0(字符模式),才能正确获取每个字符的A/D标志信息。奇偶校验:由于A/D位占据了原来奇偶校验位的位置,因此在多机模式下,硬件不提供奇偶校验功能。如果应用层需要错误检测,必须在软件层面实现。手册中建议,如果不需要8位数据,可以使用5、6或7位字符,空出的最高位由软件计算并附加奇偶校验。
接收器行为:
- 当接收器被禁用时:它只接收A/D位为1(地址)的字符,并将其存入FIFO,同时置位
RxRDY。A/D位为0(数据)的字符被直接丢弃。 - 当接收器被启用时:所有字符(无论地址还是数据)都会被接收并存入FIFO。
- 当接收器被禁用时:它只接收A/D位为1(地址)的字符,并将其存入FIFO,同时置位
帧错误和Break检测:这些功能在多机模式下正常工作。过载错误(OE)的检测逻辑也与普通模式一致。
配置流程示例:假设主机地址为0x01,从机地址为0x02。
- 主机和从机初始化:双方均设置UMR1,
PM1:PM0=11(多机模式),ERR=0(字符模式)。从机初始化后,立即发送“接收器禁用”命令,进入监听状态。 - 主机发送地址:主机设置
PT=1,然后向发送缓冲区写入地址字符0x02。发送完成后,再设置PT=0,准备发送数据。 - 从机响应:所有从机收到地址
0x02,产生中断。从机CPU读取接收缓冲区,数据为0x02,并检查USR的PE位(此时是A/D位)为1,确认是地址。地址为0x02的从机比较成功后,发送“接收器启用”命令。 - 主机发送数据:主机开始发送数据字符,例如
0xAA,0x55等。 - 从机接收数据:只有地址0x02的从机能接收到这些数据(
PE位为0)。接收完成后,该从机再次发送“接收器禁用”命令。 - 错误处理:主机在发送完数据块后,可以发送一个特殊的地址(如0x00)作为广播地址,通知所有从机复位或执行其他操作。软件层面需要实现超时重传和确认机制来保证可靠性。
4. 核心寄存器编程指南与避坑实录
理解了原理,最终都要落到寄存器配置上。SCF5250的UART寄存器看似繁多,但按功能分类后非常清晰。这里我将结合常见问题,带你深入几个最关键寄存器。
4.1 模式寄存器(UMR1 & UMR2)配置精要
UMR1(模式寄存器1)是配置的起点,它决定了通信的基本框架。
RxRTS(Bit 7):如前所述,控制接收器自动RTS。RxIRQ(Bit 6):选择接收中断源。0选择RxRDY(收到任意字符即中断),1选择FFULL(FIFO满,即收到3个字符才中断)。在数据流稳定、单次处理数据量大的场景,使用FFULL中断可以减少CPU中断次数,提升效率。在交互式、实时性要求高的场景,使用RxRDY更及时。ERR(Bit 5):错误模式。0为字符模式(推荐),每个字符的错误状态独立;1为块模式,错误状态是自上次复位错误命令后所有字符错误的累积“或”。除非有特殊需求,否则一律使用字符模式,尤其是在多机模式下。PM1, PM0, PT(Bit 4-2):这三位共同控制奇偶校验或多机模式。参考下表进行配置:
| PM1 | PM0 | PT | 功能描述 |
|---|---|---|---|
| 0 | 0 | 0 | 偶校验 |
| 0 | 0 | 1 | 奇校验 |
| 0 | 1 | 0 | 强制校验位为0 |
| 0 | 1 | 1 | 强制校验位为1 |
| 1 | 0 | X | 无校验 |
| 1 | 1 | 0 | 多机模式,发送数据字符 |
| 1 | 1 | 1 | 多机模式,发送地址字符 |
B/C1, B/C0(Bit 1-0):选择数据位长度,5/6/7/8位可选。
UMR2(模式寄存器2)主要控制发送器和停止位。
CM(Bit 7-6):通道模式,用于选择循环模式。00正常,01自动回波,10本地环回,11远程环回。TxRTS(Bit 5):发送器RTS控制。用于在半双工通信(如RS-485)中,发送完成后自动释放总线控制权。TxCTS(Bit 4):发送器CTS使能。启用硬件流控制的关键位。SB(Bit 3-0):停止位长度。这是一个查找表,对于5位字符和6-8位字符,停止位长度范围不同。例如,SB=0111对应5位字符时是1.5位停止位,对应6-8位字符时是1位停止位。最常见的配置是0111(1位停止位)。
避坑指南:寄存器修改时机。手册用加粗的“Note”警告:UMR1、UMR2、UCSR(时钟选择寄存器)和UACR的Bit 7,只能在接收器/发送器被禁用(通过软件复位命令)后才能更改。如果你在收发器运行时修改这些寄存器,会导致不可预测的结果。安全的做法是,在修改前,先通过命令寄存器(UCR)发送“复位发送器”和“复位接收器”命令。
4.2 状态寄存器(USR)与命令寄存器(UCR)的协同操作
USR(状态寄存器)是你的“眼睛”,实时反映UART模块的状态。几个关键位:
RB(Bit 7):收到Break信号。Break是一个长时间的低电平,常用于协议帧的起始或结束标志。FE(Bit 6):帧错误。通常由波特率不匹配或噪声引起。PE(Bit 5):奇偶校验错误(或多机模式下的A/D位)。OE(Bit 4):过载错误。这是FIFO已满时新字符到来导致的,是硬件流控制要解决的核心问题。TxEMP(Bit 3):发送器空。当发送保持寄存器和发送移位寄存器都空时置位。TxRDY(Bit 2):发送器就绪。发送保持寄存器为空,可以写入新数据。FFULL(Bit 1):FIFO满。当接收FIFO中有3个字符时置位。RxRDY(Bit 0):接收器就绪。FIFO中有至少1个字符。
UCR(命令寄存器)是你的“双手”,用于控制UART的行为。它是一个只写寄存器,通过写入不同的位组合来下发命令。
MISC[2:0](Bit 5-3):杂项命令。包括复位模式寄存器指针、复位接收器、复位发送器、复位错误状态、复位Break变化中断、开始Break、停止Break。最常用的是“复位错误状态”命令(MISC=100),用于在读取错误后清除RB,FE,PE,OE位。TC[1:0](Bit 2-1):发送器命令。01使能发送器,10禁用发送器。RC[1:0](Bit 0):接收器命令。01使能接收器,10禁用接收器。
一个典型的发送-接收流程及常见问题:
- 初始化:配置UMR1、UMR2、波特率发生器。务必先发送“复位发送器”和“复位接收器”命令,将模块置于已知状态。
- 发送数据:
- 等待
USR.TxRDY == 1。 - 向发送缓冲区(UTB)写入数据。
- 如果启用了CTS流控制(
TxCTS=1),发送器会在每次发送前自动检查CTS引脚,无需软件干预。
- 等待
- 接收数据(查询法):
- 循环读取
USR.RxRDY,当其为1时,从接收缓冲区(URB)读取数据。 - 读取URB的操作会自动清除
RxRDY位。 - 读取数据后,应立即检查
RB,FE,PE,OE位以判断接收质量。 - 如果有错误,应通过UCR发送“复位错误状态”命令来清除错误标志,否则这些标志会一直存在,影响后续判断。
- 循环读取
- 接收数据(中断法):
- 配置中断掩码寄存器(UIMR),使能
RxRDY或FFULL中断。 - 在中断服务程序(ISR)中,首先读取UISR(中断状态寄存器)确定中断源。
- 然后读取URB获取数据,并处理错误。
- 重要:在ISR中读取UIPCR(输入端口变化寄存器)会清除其中的
COS位;读取UISR本身不会清除中断标志,需要通过发送特定的复位命令(如复位错误状态、复位Break变化)或读取URB(针对RxRDY)来清除。
- 配置中断掩码寄存器(UIMR),使能
常见问题排查实录:
问题:发送数据正常,但接收不到任何数据,
RxRDY永远为0。- 排查1:检查波特率。这是最常见的问题。用示波器测量TxD引脚,计算实际波特率是否与配置值一致。SCF5250的UART时钟来源于系统时钟分频,检查波特率发生器寄存器(UBG1, UBG2)的计算值是否正确。
- 排查2:检查硬件连接。确认RxD、TxD线是否接反,地线是否共地。
- 排查3:检查接收器是否使能。确认在初始化后执行了“接收器使能”命令(向UCR写入
RC=01)。很多新手会配置好寄存器却忘了发使能命令。 - 排查4:检查循环模式。确认UMR2的
CM位是00(正常模式),而不是意外配置成了某种环回模式。
问题:能收到数据,但全是乱码,且伴随持续的帧错误(FE)。
- 排查1:波特率轻微不匹配。即使起始位能被检测到,但每个比特的采样点会逐渐漂移,导致采样到错误的值。确保通信双方使用相同的时钟源和精确的波特率分频系数。
- 排查2:数据格式不一致。检查双方的数据位长度(UMR1的
B/C)、停止位长度(UMR2的SB)、奇偶校验设置(UMR1的PM,PT)是否完全一致。一个8位无校验的设备与一个7位偶校验的设备通信,必然产生乱码和帧错误。
问题:通信一段时间后,数据丢失,且出现过载错误(OE)。
- 排查1:未使用流控制,且接收方处理速度慢。这是典型的缓冲区溢出。解决方案:a) 降低波特率;b) 优化接收方软件,提高数据处理速度;c)启用硬件RTS/CTS流控制(设置
RxRTS=1,TxCTS=1并正确连接硬件)。 - 排查2:中断服务程序处理太慢或中断被屏蔽。如果使用中断接收,确保ISR执行时间足够短,且没有长时间关闭全局中断。
FFULL中断表示FIFO已满(3个字符),你必须在这个中断产生后尽快取走数据。
- 排查1:未使用流控制,且接收方处理速度慢。这是典型的缓冲区溢出。解决方案:a) 降低波特率;b) 优化接收方软件,提高数据处理速度;c)启用硬件RTS/CTS流控制(设置
问题:多机模式下,从机收不到主机发送的数据字符。
- 排查1:从机地址匹配后,未启用接收器。这是最关键的步骤。从机CPU在中断中比较地址匹配后,必须立即向UCR写入“接收器使能”命令。
- 排查2:主机发送数据字符时,A/D位设置错误。主机在发送地址字符后,必须将UMR1的
PT位改为0,再发送数据字符。如果PT位仍为1,所有从机都会将数据字符当作地址字符处理,而地址字符只有在接收器禁用时才会被存入FIFO(对于非匹配地址的从机)或产生中断(对于匹配地址的从机,但此时其接收器已启用,行为不同)。 - 排查3:从机读取数据后,未检查A/D位。在多机模式下,
PE位存储的是A/D位。从机需要判断读到的字符是地址(PE=1)还是数据(PE=0),以进行不同的处理。
通过深入理解这些寄存器每一位的含义和它们之间的联动关系,你就能从“配置驱动”的层面,上升到“驾驭通信”的层面,从而设计出稳定、可靠的UART通信系统。记住,UART看似简单,但稳健的通信离不开对每一个细节的深思熟虑和反复验证。