目录

1. RS232通信原理
RS232是一种全双工串行通信标准,最早由电子工业协会(EIA)在1962年发布,后经多次修订。它采用单端信号传输,使用两根线(TX 和 RX)实现双向通信。RS232的电平标准与TTL/CMOS 不同:
逻辑1(MARK):-3V至-15V
逻辑0(SPACE):+3V至+15V
这种负逻辑和较大的电压摆幅使得RS232能够抵抗一定的噪声干扰,但也限制了其传输距离(通常不超过 15 米)和传输速率(最高约20kbps)。RS232通常用于近距离设备通信,如计算机与调制解调器、打印机或工业设备的连接。
2. RS485通信原理
RS485是一种半双工串行通信标准,由TIA/EIA-485-A标准定义。它采用差分信号传输,使用两根线(A和B)实现多点通信。RS485的电平标准:
逻辑1:A-B < -200mV
逻辑0:A-B > +200mV
差分信号传输使得RS485具有更强的抗干扰能力,支持更远的传输距离(最长1200米)和更高的传输速率(最高10Mbps,距离与速率成反比)。RS485支持多节点通信(最多32个节点),因此常用于工业自动化、楼宇控制等需要长距离和多设备通信的场景。
3. RS232与RS485主要区别
| 特性 | RS232 | RS485 |
|---|---|---|
| 信号类型 | 单端 | 差分 |
| 通信方式 | 全双工(两根线) | 半双工(两根线) |
| 电平标准 | -3V~-15V (逻辑 1),+3V~+15V (逻辑 0) | A-B <-200mV (逻辑 1),A-B > +200mV (逻辑 0) |
| 传输距离 | 最大 15 米 | 最大 1200 米(9600bps 时) |
| 传输速率 | 最高 20kbps | 最高 10Mbps(短距离) |
| 节点数量 | 点对点 | 最多 32 个节点 |
| 抗干扰能力 | 较弱 | 强 |
| 线缆要求 | 普通双绞屏蔽线 | 特性阻抗 120Ω 的差分屏蔽线 |
4. RS232与RS485优缺点分析
RS232的优点:
- 实现简单,只需两根信号线(TX/RX)
- 历史悠久,兼容性好,大多数设备支持
- 适合近距离、低速率通信
RS232的缺点:
- 传输距离短
- 抗干扰能力弱
- 不支持多节点通信
- 电平转换复杂(需专用芯片如MAX232)
RS485的优点:
- 传输距离远
- 抗干扰能力强
- 支持多节点通信
- 功耗低
- 传输速率高
RS485的缺点:
- 半双工通信,需要控制信号切换发送/接收模式
- 布线要求高(需使用差分线)
- 需额外的收发器芯片(如MAX485)
- 设计复杂度较高(需处理总线竞争问题)
5.Verilog实现代码
RS232实现代码
// RS232 UART模块 - 实现基本的发送和接收功能
module rs232_uart (
input wire clk, // 系统时钟
input wire rst_n, // 复位信号,低电平有效
input wire [7:0] tx_data, // 发送数据
input wire tx_en, // 发送使能
output reg tx_done, // 发送完成标志
output reg tx, // 发送数据线
input wire rx, // 接收数据线
output reg [7:0] rx_data, // 接收数据
output reg rx_done // 接收完成标志
);
// 参数定义
parameter BAUD_RATE = 9600; // 波特率
parameter CLK_FREQ = 50_000_000; // 系统时钟频率
parameter BAUD_DIV = CLK_FREQ / BAUD_RATE; // 波特率分频系数
// 内部信号定义
reg [15:0] baud_cnt; // 波特率计数器
reg baud_tick; // 波特率时钟脉冲
reg [3:0] tx_state, rx_state; // 发送/接收状态机
reg [3:0] tx_bit_cnt, rx_bit_cnt; // 发送/接收位计数器
reg [7:0] tx_buffer; // 发送数据缓冲区
reg rx_d1, rx_d2; // 接收信号同步寄存器
// 波特率发生器
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
baud_cnt <= 16'd0;
baud_tick <= 1'b0;
end
else begin
if (baud_cnt >= BAUD_DIV - 1) begin
baud_cnt <= 16'd0;
baud_tick <= 1'b1;
end
else begin
baud_cnt <= baud_cnt + 1'b1;
baud_tick <= 1'b0;
end
end
end
// 发送状态机
localparam TX_IDLE = 4'd0;
localparam TX_START = 4'd1;
localparam TX_DATA = 4'd2;
localparam TX_STOP = 4'd3;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
tx_state <= TX_IDLE;
tx <= 1'b1; // 空闲状态为高电平
tx_bit_cnt <= 4'd0;
tx_done <= 1'b0;
end
else begin
case (tx_state)
TX_IDLE: begin
tx_done <= 1'b0;
if (tx_en) begin
tx_buffer <= tx_data;
tx_state <= TX_START;
end
else begin
tx_state <= TX_IDLE;
end
end
TX_START: begin
if (baud_tick) begin
tx <= 1'b0; // 发送起始位(低电平)
tx_state <= TX_DATA;
tx_bit_cnt <= 4'd0;
end
end
TX_DATA: begin
if (baud_tick) begin
tx <= tx_buffer[tx_bit_cnt];
if (tx_bit_cnt >= 4'd7) begin
tx_state <= TX_STOP;
end
else begin
tx_bit_cnt <= tx_bit_cnt + 1'b1;
end
end
end
TX_STOP: begin
if (baud_tick) begin
tx <= 1'b1; // 发送停止位(高电平)
tx_done <= 1'b1; // 发送完成
tx_state <= TX_IDLE;
end
end
default: tx_state <= TX_IDLE;
endcase
end
end
// 接收信号同步(消除亚稳态)
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
rx_d1 <= 1'b1;
rx_d2 <= 1'b1;
end
else begin
rx_d1 <= rx;
rx_d2 <= rx_d1;
end
end
// 接收状态机
localparam RX_IDLE = 4'd0;
localparam RX_START = 4'd1;
localparam RX_DATA = 4'd2;
localparam RX_STOP = 4'd3;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
rx_state <= RX_IDLE;
rx_bit_cnt <= 4'd0;
rx_done <= 1'b0;
rx_data <= 8'd0;
end
else begin
case (rx_state)
RX_IDLE: begin
rx_done <= 1'b0;
if (rx_d2 == 1'b0) begin // 检测到起始位
rx_state <= RX_START;
end
end
RX_START: begin
if (baud_tick) begin
// 确认起始位中点
if (rx_d2 == 1'b0) begin
rx_state <= RX_DATA;
rx_bit_cnt <= 4'd0;
end
else begin
rx_state <= RX_IDLE;
end
end
end
RX_DATA: begin
if (baud_tick) begin
// 在每个数据位的中点采样
rx_data[rx_bit_cnt] <= rx_d2;
if (rx_bit_cnt >= 4'd7) begin
rx_state <= RX_STOP;
end
else begin
rx_bit_cnt <= rx_bit_cnt + 1'b1;
end
end
end
RX_STOP: begin
if (baud_tick) begin
if (rx_d2 == 1'b1) begin // 确认停止位
rx_done <= 1'b1; // 接收完成
end
rx_state <= RX_IDLE;
end
end
default: rx_state <= RX_IDLE;
endcase
end
end
endmodule
RS485实现代码
// RS485 UART模块 - 基于RS232 UART,增加方向控制
module rs485_uart (
input wire clk, // 系统时钟
input wire rst_n, // 复位信号,低电平有效
input wire [7:0] tx_data, // 发送数据
input wire tx_en, // 发送使能
output reg tx_done, // 发送完成标志
input wire rx, // 接收数据线
output reg [7:0] rx_data, // 接收数据
output reg rx_done, // 接收完成标志
output reg rs485_dir // RS485方向控制信号,1为发送,0为接收
);
// 内部信号定义
wire tx_internal; // 内部发送信号
reg tx_en_internal; // 内部发送使能
reg [1:0] state; // 状态机状态
// 实例化RS232 UART核心模块
rs232_uart uart_core (
.clk(clk),
.rst_n(rst_n),
.tx_data(tx_data),
.tx_en(tx_en_internal),
.tx_done(tx_done),
.tx(tx_internal),
.rx(rx),
.rx_data(rx_data),
.rx_done(rx_done)
);
// RS485方向控制状态机
localparam IDLE = 2'd0;
localparam TX_PREPARE = 2'd1;
localparam TX_ACTIVE = 2'd2;
localparam RX_READY = 2'd3;
reg [7:0] delay_cnt; // 延时计数器
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
rs485_dir <= 1'b0; // 默认处于接收状态
tx_en_internal <= 1'b0;
delay_cnt <= 8'd0;
end
else begin
case (state)
IDLE: begin
rs485_dir <= 1'b0; // 保持接收状态
tx_en_internal <= 1'b0;
if (tx_en) begin
state <= TX_PREPARE;
delay_cnt <= 8'd0;
end
end
TX_PREPARE: begin
rs485_dir <= 1'b1; // 切换到发送状态
delay_cnt <= delay_cnt + 1'b1;
// 等待一段时间确保RS485收发器完成切换
if (delay_cnt >= 8'd10) begin
tx_en_internal <= 1'b1; // 启动发送
state <= TX_ACTIVE;
end
end
TX_ACTIVE: begin
tx_en_internal <= 1'b1; // 保持发送使能
if (tx_done) begin
tx_en_internal <= 1'b0;
delay_cnt <= 8'd0;
state <= RX_READY;
end
end
RX_READY: begin
rs485_dir <= 1'b0; // 切换回接收状态
delay_cnt <= delay_cnt + 1'b1;
// 等待一段时间确保RS485收发器完成切换
if (delay_cnt >= 8'd10) begin
state <= IDLE;
end
end
default: state <= IDLE;
endcase
end
end
// RS485差分输出(实际应用中需连接到RS485收发器)
// 此处仅为示意,实际硬件连接需要使用如MAX485等芯片
// RS485_A <= tx_internal;
// RS485_B <= ~tx_internal;
endmodule
1万+

被折叠的 条评论
为什么被折叠?



