基本概念
通用异步收发传输器。数据发送时将并行数据转换成串行数据。数据接收时将串行数据转换成并行数据,可以实现全双工传输和接收。(RS232,RS449,RS423..)
通信协议
UART通信在使用前需要做多项设置,最常见的设置包括数据位数、波特率大小、奇偶校验类型和停止位数。
数据位(Data bits):该参数定义单个UART数据传输在开始到停止期间发送的数据位数。可选择为:5、6、7 或者 8(默认)。
在每个字节的数据位发送完成之后,发送停止位,来标志着一次数据传输完成,同时用来帮助接受信号方硬件重同步。可选择为:1(默认)、1.5 或者 2 位。
原理图:
![](https://i-blog.csdnimg.cn/blog_migrate/54acaeaa77b8d2ccc2d640c12a2c6a43.png)
![](https://i-blog.csdnimg.cn/blog_migrate/9013add8fecf9ec373795a5525f36d72.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d8af6bfb83b845615e17e194e6ace484.png)
设计流程与代码
设计流程:当发送使能信号来时,将输入数据放入寄存器以消除暂稳态。同时另输出的状态信号为1,之后通过波特率对应的计数器去控制输出。
module uart_tx(Clk,Rst_n,data_byte,baud_set,send_en,Rs232_Tx,Tx_Done,uart_state);
input Clk;
input Rst_n;
input [7:0]data_byte;
input [2:0]baud_set;
input send_en;
output reg Rs232_Tx;
output reg Tx_Done;
output reg uart_state;
reg BPS_CLK;
reg [3:0]BPS_cnt;
reg [12:0]CNT_MAX; //分频计数最大值
reg [12:0]cnt;
reg [7:0]data_reg1;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
data_reg1 <= 8'd0;
else if(send_en)
data_reg1 <= data_byte;
else
data_reg1 <= data_reg1;
always@(*)begin
case(baud_set)
3'd0:CNT_MAX=13'd5207;
3'd1:CNT_MAX=13'd2603;
3'd2:CNT_MAX=13'd1301;
3'd3:CNT_MAX=13'd868;
3'd4:CNT_MAX=13'd434;
default:CNT_MAX=13'd5207;
endcase
end
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
cnt <= 13'd0;
else if(uart_state)begin
if(cnt == CNT_MAX)
cnt <= 13'd0;
else
cnt <= cnt +1'b1;
end
else
cnt <= cnt;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
BPS_CLK <= 1'b0;
else if(cnt == 13'd1)
BPS_CLK <= 1'b1;
else
BPS_CLK <= 0;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
BPS_cnt <= 4'd0;
else if(BPS_cnt == 4'd11)
BPS_cnt <= 4'd0;
else if (BPS_CLK)
BPS_cnt <= BPS_cnt + 1'b1;
else
BPS_cnt <= BPS_cnt;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
Tx_Done <= 1'b0;
else if(BPS_cnt == 4'd11)
Tx_Done <= 1'b1;
else
Tx_Done <= 1'b0;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
uart_state <= 1'b0;
else if(send_en)
uart_state <= 1'b1;
else if(BPS_cnt == 4'd11)
uart_state <= 1'b0;
else
uart_state <= uart_state;
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)
Rs232_Tx = 1'b1;
else begin
case(BPS_cnt)
4'd0:Rs232_Tx = 1'b1;
4'd1:Rs232_Tx = 1'b0;
4'd2:Rs232_Tx = data_reg1[0];
4'd3:Rs232_Tx = data_reg1[1];
4'd4:Rs232_Tx = data_reg1[2];
4'd5:Rs232_Tx = data_reg1[3];
4'd6:Rs232_Tx = data_reg1[4];
4'd7:Rs232_Tx = data_reg1[5];
4'd8:Rs232_Tx = data_reg1[6];
4'd9:Rs232_Tx = data_reg1[7];
4'd10:Rs232_Tx = 1'b1;
default:Rs232_Tx = 1'b1;
endcase
end
endmodule