RS-232是一种串行通信协议,用于在计算机和其他外部设备之间进行数据传输。RS-232定义了电气特性、信号级别、机械特性和传输速率等规范,为串行通信提供了一种标准化的接口。
RS-232通常使用DB9连接器,用于传输和接收数据、控制信号以及地线连接。
但除了235脚其它基本都省略了,一个发送一个接收还有个地。
rs232是单端传输,还有485,422 差分传输,485半双工,422 全双工,原理差不多
下面是verilog代码。
tx.v
module tx (input wire clk,input wire rst_n,input wire tx_begin,input wire[7:0] tx_pdata,output reg txd,output reg busy
);localparam OSC = 50_000_000;
localparam BAUD = 115200;
//localparam BAUD = 57600;
//localparam BAUD = 38400;
//localparam BAUD = 19200;localparam NUM = OSC/BAUD - 1;reg[16:0] clk_cnt;reg [1:0] stage;
reg [2:0] curbit;
reg [7:0] tx_data;
reg done;always @(posedge clk or negedge rst_n ) beginif (!rst_n ) beginbusy <= 1'b0;end else if (tx_begin === 1'b1 && busy === 1'b0 ) begin // busy ignorebusy <= 1'b1;tx_data <= tx_pdata;end else if (done) busy <= 1'b0;
endreg tx_clk_en;always @(busy) beginif(busy)tx_clk_en <= 1'b1;elsetx_clk_en <= 1'b0;
endreg tx_stage_pulse;
always @(posedge clk or negedge rst_n ) beginif (!rst_n)clk_cnt <= 0;else if( tx_clk_en === 1'b0 || clk_cnt === NUM)clk_cnt <= 0;else clk_cnt <= clk_cnt + 1;
endalways @(posedge clk) beginif (clk_cnt === 1)tx_stage_pulse <= 1'b1;elsetx_stage_pulse <= 1'b0;
endalways @(posedge clk or negedge rst_n) beginif(!rst_n) begintxd <= 1'b1;done <= 1'b0;stage <= 2'd0;end else if (busy) beginif (tx_stage_pulse) beginif (stage === 2'd0) begintxd <= 1'b0;done <= 1'b0;stage <= 2'b1;curbit <= 3'd0;end else if (stage === 2'b1) begintxd <= tx_data[curbit];if (curbit === 3'd7)stage <= 2'd2;elsecurbit <= curbit + 1;end else if (stage === 2'd2) begintxd <= 1'b1;stage <= 2'd3;end else if (stage === 2'd3) begintxd <= 1'b1;done <= 1'b1;stage <= 2'd0;endendend else begintxd <= 1'b1;done <= 1'b0;stage <= 2'd0;end
endendmodule
测试
uart_test.v
module uart_test (input wire clk,input wire rst_n,output wire txd
);reg tx_begin;
reg[7:0] tx_data = 0;reg[31:0] cnt;
parameter maxcnt = 32'd1500 ;
wire busy;always @(posedge clk or negedge rst_n) beginif(!rst_n)cnt <= 0;else if (cnt == maxcnt) begincnt <= 0;if(!busy) tx_data <= (tx_data + 1) & 8'h7f ;tx_begin <= 1'b1;end else begintx_begin <= 1'b0;cnt <= cnt+1;end
endtx tx1(clk,rst_n,tx_begin,tx_data,txd,busy);endmodule
testbench
test.v
module test;reg rst_n=1 ;initial begin$dumpfile("test.vcd");$dumpvars(0, test);#10 rst_n = !rst_n;#30 rst_n = !rst_n;#100000 $finish;
endreg clk = 0;
always #1 clk = !clk;wire txd;
uart_test uart1(clk,rst_n,txd);endmodule
两个问题,一帧数据传输完成前,再次接到发送指令,直接丢弃,因为中间即使停止, 对方也会以为这是数据直到完成这一帧 , 有可能会打乱时序 ,或用FIFO。引出一位busy忙标志位。
二停止位,有1位,1.5位,2位的,测试了下快速发送,用1位115200 57600没有乱码,速度降下去后会出现乱码,两位停止位乱码消失,稳定起见,停止位两位。