1. 项目概述与UART协议基础
在嵌入式系统开发中,UART串口通信是最基础也最常用的外设接口之一。这次我在正点原子启明星开发板(Zynq XC7Z010)上从零实现了UART通信协议,过程中遇到了不少值得记录的技术细节和问题。
UART(通用异步收发器)作为一种异步串行通信协议,其核心特点是通信双方不需要共享时钟信号,而是通过预先约定的波特率来实现数据同步。这种特性使得UART非常适合用于设备间的简单数据交换,比如FPGA与PC之间的调试信息传输。
提示:异步通信的关键在于收发双方必须严格遵循相同的波特率设置,即使有微小偏差也会导致数据错误。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 关键参数计算与采样策略
2.1 波特率生成原理
我的开发板系统时钟为50MHz,目标波特率设置为常见的9600bps。要实现精确的波特率生成,需要计算每个bit位对应的时钟周期数:
code复制CNT_MAX = 系统时钟频率 / 波特率
= 50,000,000 / 9600
≈ 5208个时钟周期/bit
这意味着FPGA需要每计数5208个时钟周期,就完成一个bit位的发送或接收。在实际操作中,我使用了13位宽的计数器(最大可表示8191)来满足这个需求。
2.2 中间采样技术详解
异步通信中最关键的挑战是如何在噪声环境中可靠地识别数据。我采用了"中间采样"策略,即在每个bit周期的正中间时刻进行采样,这样可以最大程度避开信号跳变边缘的不稳定区域。
具体实现时:
- 当检测到起始位下降沿后,计数器从0开始计数
- 当计数器达到CNT_MAX/2(即2604)时进行采样
- 这种技术显著提高了通信的可靠性,实测中即使在有轻微干扰的环境下也能稳定工作
3. Verilog模块设计与实现
3.1 接收模块(uart_rx.v)优化
接收模块是UART实现中最复杂的部分,我采用了三段式状态机设计:
- 空闲状态:持续监测RX线路,等待起始位下降沿
- 起始位确认:检测到下降沿后延时半个bit周期进行二次确认,有效滤除噪声干扰
- 数据接收:在位周期中间点依次采样8个数据位
verilog复制// 下降沿检测逻辑
always @(posedge sys_clk) begin
