当前位置: 首页 > news >正文

FPGA串口通信实现方案

目录

什么是串口

系统架构

UART发送模块 (TX)

UART接收模块 (RX)

波特率发生器

FIFO缓冲区

关键参数

波特率计算

器波特率发生

串口帧结构波形图

UART发送模块

UART接收模块


什么是串口

串口(Serial Port),也叫串行通信接口,是一种用于在计算机与外部设备之间逐位顺序传输数据的通信接口。

  1. 并行通信: 同时使用多条数据线(例如 8 条、16 条、32 条)来传输数据。每个时钟周期可以传输多个比特(一个字节或更多)。速度快,但线缆复杂、成本高、易受干扰、传输距离短。典型的并行接口如早期的打印机接口(LPT 端口)。

  2. 串行通信: 只使用一条数据线(或者一对差分线)来传输数据。数据的所有比特按照顺序,一个接一个地在这条线上发送出去。速度相对并行慢,但线缆简单(最少只需要 2-3 根线:发送、接收、地线)、成本低、抗干扰能力强、传输距离远。

关键组成部分

串口协议通常涵盖以下层面:

  • 物理层 (硬件接口标准 & 电气特性)

    • RS-232: 最经典标准,使用±3V至±15V电平(负逻辑:+3~+15V = 0, -3~-15V = 1),常见于老式电脑、工控设备。传输距离短(<15米)点对点连接。

    • RS-422: 差分信号(平衡传输),抗干扰强,全双工点对多点(1主多从),传输距离长(可达1200米)

    • RS-485: RS-422的扩展,半双工或全双工真正的多点总线(多主多从),广泛用于工业自动化(Modbus RTU等)。

    • TTL UART: 芯片级电平(通常 0V = 0, 3.3V/5V = 1),距离极短(板级或短电缆)。需要电平转换芯片(如MAX232)才能连接RS-232设备。

  • 数据链路层 (帧格式 & 时序)

    • UART (Universal Asynchronous Receiver/Transmitter): 这是最核心的异步串行通信协议引擎。它定义了数据的打包和解包方式,但不包括物理电平。

    • 关键参数 (双方必须严格匹配)

      • 波特率 (Baud Rate): 每秒传输的符号数(通常等同于比特率bps)。常见值:9600, 19200, 38400, 57600, 115200等。误差容忍度低(通常<3%)

      • 数据位 (Data Bits): 每个数据帧的有效数据长度(通常7或8位)。

      • 停止位 (Stop Bits): 标志数据帧结束(通常1位,有时1.5或2位)。

      • 校验位 (Parity Bit): 简单的错误检测机制(奇校验/偶校验/无校验)。

      • 流控制 (Flow Control): 管理发送速率,防止接收方溢出(硬件RTS/CTS, 软件

系统架构

UART发送模块 (TX)

将并行数据转换为串行输出,添加起始位、停止位和可选的校验位。

UART接收模块 (RX)

采样串行输入,检测起始位,提取数据位,验证停止位和校验位。

波特率发生器

通过分频产生精确的波特率时钟,支持多种常用波特率。

FIFO缓冲区

解决发送端和接收端速度不匹配问题,提高系统稳定性。

关键参数

参数说明
波特率115200 bps可配置为9600, 19200, 38400等
数据位8位支持5-9位数据位
停止位1位支持1、1.5、2位停止位
校验位支持奇校验、偶校验、无校验
系统时钟50 MHzFPGA主时钟频率
FIFO深度16字节发送和接收缓冲区大小

波特率计算

分频系数 = 系统时钟频率 / 波特率

50,000,000 / 115200 ≈ 434

器波特率发生

module baud_gen
( input clk, input reset, input [15:0] baud_rate, output reg baud_tick ); 
reg [15:0] counter; 
always @(posedge clk or posedge reset) begin if (reset) begin counter <= 0; 
baud_tick <= 0; 
end else if (counter == baud_rate - 1) begin counter <= 0; 
baud_tick <= 1; 
end else begin counter <= counter + 1; 
baud_tick <= 0; 
end end endmodule

串口帧结构波形图

UART发送模块

module uart_tx( input clk, reset, 
input [7:0] data_in, input data_valid, 
input baud_tick, output reg tx, output reg tx_busy ); 
reg [3:0] state; reg [3:0] bit_count;
reg [7:0] data_reg; 
parameter IDLE = 0, START = 1, DATA = 2, STOP = 3; 
always @(posedge clk or posedge reset) 
begin if (reset)begin state <= IDLE; 
tx <= 1'b1; // 空闲状态高电平 
tx_busy <= 0; 
end else if (baud_tick)begin 
case (state) 
IDLE: begin tx <= 1'b1; 
tx_busy <= 0; 
if (data_valid) 
begin state <= START;data_reg <= data_in; 
tx_busy <= 1; 
end end START: 
begin tx <= 1'b0; // 起始位 
bit_count <= 0;state <= DATA; 
end 
DATA: begin tx <= data_reg[bit_count]; 
if (bit_count == 7) 
begin state <= STOP; 
endelse beginbit_count <= bit_count + 1; 
end 
end 
STOP: begin tx <= 1'b1; // 停止位 
state <= IDLE; 
end
endcase 
end 
end endmodule

UART接收模块

module uart_rx( input clk, reset, input rx,

baud_tick, output reg [7:0] data_out, 

output reg data_valid ); 

reg [3:0] state;

 reg [3:0] bit_count;

 reg [7:0] data_reg; reg [3:0]

sample_count; 

parameter 

IDLE = 0,

START = 1,

DATA = 2,

STOP = 3; 

always @(posedge clk or posedge reset) 

begin if (reset) 

begin state <= IDLE;

data_out <= 0;

data_valid <= 0; 

end 

else if (baud_tick)

 begin case (state)

IDLE: begin data_valid <= 0;

 if (!rx) begin // 检测起始位 

state <= START;

sample_count <= 0; 

end 

end 

START: 

begin if (sample_count == 7) 

begin // 在起始位中间采样

 if (!rx) begin // 确认起始位

 state <= DATA;

bit_count <= 0;

sample_count <= 0; 

end 

else begin 

state <= IDLE; 

end end else begin sample_count <= sample_count + 1;

 end end DATA: 

begin if (sample_count == 15) begin // 在数据位中间采样

 data_reg[bit_count] <= rx; sample_count <= 0;

 if (bit_count == 7) begin state <= STOP; 

end 

else begin 

bit_count <= bit_count + 1; 

end 

end 

else

 begin sample_count <= sample_count + 1; 

end

 end STOP:

 begin if (sample_count == 15) begin data_out <= data_reg; // 锁存数据 

data_valid <= 1; // 数据有效 

state <= IDLE;

 end e

lse 

begin 

sample_count <= sample_count + 1; 

end 

end

 endcase 

end 

end endmodule

http://www.xdnf.cn/news/1309537.html

相关文章:

  • Qt QDateTime时间部分显示为全0,QTime赋值后显示无效问题【已解决】
  • 【C++】C++11
  • Maven私服配置模版
  • 深入详解PCB布局布线技巧-去耦电容的摆放位置
  • IOMMU的2级地址翻译机制及多级(2~5)页表查找
  • Python 项目高频设计模式实战指南:从理念到落地的全景剖析
  • 电路方案分析(二十一)笔记本电脑散热风扇参考设计
  • 【运维心得】三步更换HP笔记本电脑外壳
  • 玄机靶场 | 日志分析-Tomcat日志分析
  • Tomcat架构深度解析:从Server到Servlet的全流程揭秘
  • Jenkins常见问题及解决方法
  • js原生实现手写签名与使用signature_pad库实现手写签名
  • 【科研绘图系列】R语言在DOM再矿化数据分析与可视化中的应用
  • 【CF】Day128——杂题 (图论 + 贪心 | 集合 + 贪心 + 图论 | 二分答案 + 贪心)
  • bev 感知算法 近一年来的新进展
  • echarts 画一个饼图,并且外围有一个旋转动画
  • pytest tmpdir fixture介绍(tmpdir_factory)(自动在测试开始前创建一个临时目录,并在测试结束后删除该目录)
  • 【LeetCode题解】LeetCode 35. 搜索插入位置
  • flowable汇总查询方式
  • ktg-mes 改造成 Saas 系统
  • Golang分布式事务处理方案
  • ROS move_base 混合功能导航 RealSense D435i + 3D 点云地图 + 楼层切换 + 路径录制 + 路径规划
  • 适合2D而非3D的游戏
  • Rust学习笔记(四)|结构体与枚举(面向对象、模式匹配)
  • 从舒适度提升到能耗降低再到安全保障,楼宇自控作用关键
  • 奈飞工厂 —— 算法优化实战推荐
  • JavaScript手录17-原型
  • 2025年生成式引擎优化(GEO)服务商技术能力评估报告
  • 【Docker】Ubuntu上安装Docker(网络版)
  • [创业之路-550]:公司半年度经营分析会 - 常见差距与根因分析示例