尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Vivado中UART核与RS422串口通信调试实战:从配置到乱码排除

Vivado中UART核与RS422串口通信调试实战:从配置到乱码排除 简介Vivado环境下UART串口通信与RS-422差分接口的FPGA实现方案面向嵌入式工程师、FPGA学习者和科研项目适用于需要快速完成串口IP核配置、行为仿真及硬件验证的场合。压缩包共151个文件约866KB内含Vivado工程文件xpr/prj、RTL源码v、Tcl/Bat运行脚本、综合与仿真日志/报告log/rpt以及设计检查点dcp和调试数据库wdb/mem可完整展示从创建工程、配置波特率与数据位、连接AXI总线到时序分析和上板下载的流程这些文件覆盖了从工程建立到生成比特流的各阶段目录结构较清晰。资料系统梳理了UART帧结构、奇偶校验、中断处理等基础原理并重点扩展RS-422差分信号的特点与抗干扰措施帮助读者理解半双工/全双工通信和远距离传输设计。随附的仿真工程可在部署前校验收发时序与数据格式观察出错时的波形定位问题减少硬件调试成本实际项目中也可参考其信号连接与模块划分方式。已有2339人学习适合需要入门FPGA串口通信或借鉴完整工程结构的开发者。1. 从RS232到RS422Vivado串口通信的痛点与突破口调试一块带FPGA的板卡时最常遇到的就是串口通信问题明明在Vivado里加了一个UART核上位机却收不到数据或者收到一串乱码。换成RS422接口后问题更多——差分接线正反、终端电阻、收发器使能、波特率误差哪一环没处理好都会让整个链路静默。Vivado中的UART核确实能省掉自己写波特率生成器和收发状态机的功夫但它只负责TTL电平串行协议RS422的物理层还需要外部收发器配合。真正要把UART、Vivado、422串口串成一条稳定链路需要同时搞懂IP核参数、寄存器访问和差分信号设计。这篇文章以一个RS422设备的实际调试为背景讲清楚在Vivado里从零配置UART核、连接外部收发器、定位乱码问题的完整路径适合刚接触FPGA串口调试的工程师也适合被422丢数据折腾过、想系统排查一遍的人。2. Vivado中的UART核协议原理与选型思路2.1 UART帧结构与波特率误差容限UART是异步协议收发两端没有共享时钟靠约定的波特率在每个数据位中间采样。空闲时TXD保持高电平发送方拉低一个bit时间作为起始位然后从低位到高位输出数据位最后是停止位。接收方会以波特率的16倍频采样检测到下降沿后从位中间位置读取电平这样能容忍一定的时钟偏差。在Vivado中UART核内部的波特率发生器需要把系统时钟分频到期望波特率。分频关系为分频值 系统时钟频率 / (波特率 × 16)。以100MHz时钟、115200波特率为例用Python可以快速估算误差clk_freq 100_000_000 baud 115_200 div clk_freq // (baud * 16) actual_baud clk_freq / (div * 16) error (actual_baud - baud) / baud print(f分频值: {div}) print(f实际波特率: {actual_baud:.2f}) print(f误差: {error:.4%})这个例子算出的div54实际波特率115740.74误差约0.47%在UART可接受的±2%以内。但换成9600波特率、60MHz时钟时误差就可能接近无法容忍的边界。RS422的长线传输本身会引入上升沿变缓如果再叠加波特率误差很容易出现乱码或偶发性丢字节。所以配置UART核时不能只看界面里填了多少波特率要结合挂载的时钟频率检查实际误差。2.2 Vivado中的UART核类型与选择Vivado IP Catalog里最常见的两种核是AXI UART Lite和AXI UART 16550。AXI UART Lite占用资源少寄存器简单适合在MicroBlaze软核或自研AXI逻辑中做调试串口AXI UART 16550是PC经典串口控制器的移植版本寄存器更丰富带深度FIFO和完整中断状态适合需要与旧式软件高度兼容的场景。特性AXI UART LiteAXI UART 16550总线接口AXI4-LiteAXI4-LiteFIFO深度默认16字节可配置默认64字节可配置中断支持仅发送/接收空满完整中断源含超时波特率精度整数分频误差取决于时钟整数分频内部自动计算典型用途简单调试、裸机串口Linux串口、高可靠收发选型时看两个维度一是处理器或逻辑侧访问复杂度二是中断和FIFO是否满足数据吞吐。只做一条命令交互AXI UART Lite足够要连续传输大块数据且不想频繁轮询就选16550并加大FIFO。对于RS422场景UART核选型对物理层没有直接影响因为核输出的是单端TTL信号差分转换完全在片外。2.3 RS422与UART核的物理层对接RS422是差分全双工标准四根线分别为T、T-、R、R-。它的优势是共模抑制能力强传输距离远速率也可以做到比RS232高很多。UART核的uart_txd是单端信号进入外部收发器MAX3490或MAX490的DI引脚经过差分驱动器输出到T和T-对端发过来的差分信号进入收发器的A/B引脚恢复成TTL电平从RO引脚送回FPGA的uart_rxd。很多工程师第一次接RS422时会把T接到对端的T这其实不对。RS422全双工收发各占一对线发送端Y/Z要接到对端接收端的A/B也就是自己的T要接对方的R。如果接反对端接收器会一直输出固定电平FPGA侧看到的就是uart_rxd恒为高或恒为低没有任何数据跳变。关于终端电阻RS422规范要求在接收端并联一个120欧电阻吸收反射但板内走线短、波特率低于1Mbps时可以不加。加了不会出错只是功耗稍大。Vivado工程里不需要为RS422做特殊原语约束的是FPGA引脚电平比如LVCMOS33或LVCMOS25具体取决于收发器的电压域。3. 在Vivado中配置UART核并生成可用的串口硬件3.1 创建工程并添加AXI UART Lite核打开Vivado 2023.2新建RTL工程并选好FPGA型号。在IP Catalog中输入UART搜索找到AXI UART Lite并双击添加。如果是Block Design流程直接拖入画布如果习惯纯Verilog可以先用IP例化模板生成HDL文件再手动连接AXI4-Lite接口。绝大多数板卡调试工程会伴随MicroBlaze或Zynq处理器所以常见的做法是在Block Design里添加。添加完成后需要至少一个AXI主设备来访问UART核。如果没有软核可以用Vivado自带的一个AXI Verification IP做测试或者直接用System ILA观察引脚波形。这里以Block Design为例创建Block Design添加MicroBlaze、DDR、UART核等。双击UART核进入配置界面。勾选需要的选项波特率、数据位、校验位都在这设置。Run Connection Automation自动连线时钟、复位和AXI接口。生成输出产品并综合布局布线最终得到比特流。这一步的坑通常在时钟频率。UART核需要知道挂载的时钟频率连接自动化默认可能把时钟连错。检查Block Design里连接到UART核的时钟是否是100MHz或实际值否则内部波特率发生器会按错误频率计算。3.2 UART核核心参数配置AXI UART Lite的配置界面参数看起来不多但每一项都直接影响RS422链路能否正常通信。参数推荐值说明Data Bits8串口最常见对端也设为8ParityNone与对端一致常用无校验Stop Bits1多数设备默认1位停止位Baud Rate115200需要与上位机和设备统一Use Interrupt可勾选接收数据量大时建议开启FIFO Depth16发送和接收各16字节Frequency与实际时钟一致波特率分频依赖这个值尤其注意Frequency这个参数。在AXI UART Lite配置界面里它不会自动读取Block Design的时钟频率需要手动确认。如果这里填错界面显示的波特率是虚的实际波形频率会完全不同。RX FIFO和TX FIFO深度默认16字节对115200波特率来说如果上位机一次发几百字节而处理器来不及读取数据就会溢出。加深FIFO或启动中断是两种常用缓解手段。3.3 连接外部RS422收发器的引脚约束UART核输出uart_txd和uart_rxd在顶层设计里这两根线要引到FPGA引脚然后连接到外部RS422收发器。假设收发器使用3.3V供电约束写法如下set_property -dict {PACKAGE_PIN D11 IOSTANDARD LVCMOS33} [get_ports uart_txd] set_property -dict {PACKAGE_PIN C12 IOSTANDARD LVCMOS33} [get_ports uart_rxd] set_property PULLUP [get_ports uart_rxd]这里给uart_rxd加PULLUP是为了防止收发器未上电时引脚浮空导致UART核误检测到起始位收到一堆0xFF。很多板子的RS422收发器RO端会带内部上拉但自己画板时不可依赖约束里显式加PULLUP更稳妥。如果是收发器带使能脚还要把DE和RE连到固定电平保证驱动器和接收器一直有效。完成约束后生成比特流会看到两个引脚的电平标准是LVCMOS33。FPGA引脚不直接输出差分信号所以不需要在XDC里写DIFF_TERM或DIFFSTD那是给LVDS这类原生差分接口用的。RS422差分转换完全交给外部芯片。3.4 导出硬件并在SDK中驱动UART核生成比特流后File Export Hardware勾选包含比特流然后启动Vitis SDK或老版本Xilinx SDK。在C工程中AXI UART Lite的寄存器基地址由Address Editor分配假设为0x44A00000。典型的收发轮询代码如下#include xil_io.h #define UART_BASE 0x44A00000 #define UART_SR 0x04 #define UART_TX_FULL 0x01 #define UART_RX_VALID 0x02 void uart_send_byte(unsigned char ch) { // SR[0]1 表示发送FIFO满等待空闲 while (xil_in32(UART_BASE UART_SR) UART_TX_FULL); xil_out32(UART_BASE, ch); } unsigned char uart_recv_byte(void) { // SR[1]1 表示接收FIFO内有数据 while (!(xil_in32(UART_BASE UART_SR) UART_RX_VALID)); return (unsigned char)(xil_in32(UART_BASE) 0xFF); }代码逻辑很明确发送前检查SR寄存器bit0为1说明FIFO满必须等待接收前检查bit1为0说明无数据持续轮询。读取RBR时只取低8位因为AXI数据总线宽度可能大于8位。这种轮询方式在115200波特率下足够应对单字节交互但如果连续收发大块数据轮询会占用CPU此时应该改用中断或者把UART核的FIFO深度调大。4. RS422串口通信实战从接线到排除乱码4.1 RS422收发器选型与接线要点RS422收发器常用型号有MAX3490、MAX490、SN65HVD22等。选型时注意供电电压是否和FPGA的bank电压一致。3.3V供电的FPGA配MAX3490最方便不需要电平转换。MAX3490是全双工内部包含一个驱动器和一个接收器正好匹配UART核的txd和rxd两根线。接线顺序是FPGA的uart_txd接到MAX3490的DI引脚uart_rxd接到RO引脚。MAX3490的差分引脚Y、Z输出到连接器命名为422_T和422_T-连接器上另外两个引脚422_R和422_R-接到MAX3490的A和B。外部设备对接时自己的422_T必须连对端的422_R422_T-连对端的422_R-。这个交叉设计经常被忽略建议画板时在原理图上直接标注“发送接对方接收”减少出错。如果传输距离超过几十米或波特率高于1Mbps在接收端A和B之间并联120欧终端电阻。短距离调试可以不加但一旦出现偶发错位或持续乱码先补一个电阻再测。MAX3490的RO端在接收差分信号缺失时会输出高电平这是好事因为UART空闲态就是高电平。但如果差分接反RO会一直输出低电平FPGA侧会不停收到0x00现象与无终端电阻完全不同。4.2 在Vivado工程中做引脚与约束实战板级调试时如果发现RS422收发数据异常先检查约束文件与原理图是否一致。很多时候问题出在IO引脚分配号抄错或者把T和T-在XDC里写反。一个稳妥的方法是在约束里给收发引脚分别加注释并让硬件工程师一起核对。# FPGA - MAX3490 DI差分输出到422_T/T- set_property PACKAGE_PIN E14 [get_ports uart_txd] # MAX3490 RO - FPGA差分输入来自422_R/R- set_property PACKAGE_PIN F14 [get_ports uart_rxd] set_property IOSTANDARD LVCMOS33 [get_ports uart_txd] set_property IOSTANDARD LVCMOS33 [get_ports uart_rxd] set_property PULLUP [get_ports uart_rxd]ud引脚加了PULLUP后在收发器没焊接时FPGA读到的uart_rxd也是高电平不会误触发起始位打断正常发送流程。这已经排掉一个隐藏故障。如果板卡上有多个RS422通道建议每个通道的rxd都加PULLUP防止空闲电平悬空。约束完成后还可以用报告里的IO plan检查引脚位置。Vivado的Device视图会显示每个引脚对应的封装位置和原理图交叉验证一遍能省一晚上调试时间。4.3 用ILA和串口助手定位通信故障当上位机与FPGA之间的422链路不通时先在Vivado里插入ILA核把uart_txd和uart_rxd挂到探针上。采样时钟选择系统时钟触发条件设为uart_txd下降沿。这样能第一时间看到FPGA侧是否真的产生了UART波形。如果ILA看不到txd跳变问题在发送侧例如FIFO满标志一直有效或者CPU没有执行发送代码。如果txd有波形但上位机收不到问题在RS422物理层重点检查差分接线和收发器供电。如果txd和rxd都有波形但数据乱码多半是波特率误差、校验位不匹配或差分极性接反。下表是调试中常见的几种现象可以直接对照排查现象可能原因排查方法完全无数据ILA无波形UART核未使能、FIFO满死锁检查复位时序和SR寄存器txd有波形上位机收不到RS422差分接反、收发器未使能测量差分电压对调A/B上位机能发FPGA收不到rxd引脚悬空、RO未连接ILA看uart_rxd是否跟随发送能通信但乱码波特率误差大、校验位不匹配发送0x55量一帧位宽偶发丢字节FIFO溢出、中断响应慢加深FIFO或排查中断服务程序使用串口助手调试时先发送0x55再发送0xAA这两个值在波形上是交替的01序列方便在示波器上观察。如果发送0x55收到0x5A之类说明位顺序或采样点有问题优先怀疑波特率误差。5. 用ILA实测RS422链路波特率UART核最容易被忽略的坑UART核配置界面里填了115200实际发出的波特率可能因为整数分频而偏离几百甚至几千。RS232短距通信时这点误差不明显但RS422长线传输会把噪声和边沿变缓叠加进来导致临界状态下整帧错位。所以调试到最后别急着怀疑收发器芯片先用ILA量一次真实波特率。在Vivado里把ILA采样时钟设为系统时钟抓取uart_txd触发条件设为下降沿。抓到波形后测量相邻两个下降沿之间的采样点数。这个时间就是UART的一个bit周期。比如100MHz采样时钟下两个下降沿间隔868个周期对应波特率就是100000000/868115207.37与期望值几乎一致。如果间隔是800个周期实际波特率就是125000和115200差太远一定收不到数据。测量结果异常时回到Block Design检查UART核的Frequency参数。常见错误是把100MHz写成125MHz导致实际分频值偏小、波特率增大。修正后重新跑综合即可。除了用ILA还可以在C代码里测量接收单bit宽度。前提是外部能发送一个已知波特率的数据帧用定时器捕获每次起始后第一个下降沿和第二个下降沿的时间差。这个方法适合没有逻辑分析仪的场合但对中断精度要求高建议还是优先用ILA。RS422链路稳定验证可以做一个长时间误码统计FPGA收到数据后回发上位机对比发送和接收内容统计错误bit数。连续跑1小时无错比单独开一次串口助手测试可靠得多。核心思路是用可控的测试序列把协议和物理层分开验证——先确认FPGA内部UART环回无误再连接RS422对端测试最后接入真实设备调参数。这样一步步收窄问题范围比反复改动波特率或接口配置更高效。本文还有配套的精品资源点击获取
返回列表