大家常说的serial、UART、RS232、串口等概念究竟是怎么回事?它们之间有何联系?有何区别?下面小编会与大家一起来学习。
UARTRS232 RS485 RS422区别RS232物理接口RS485物理接口RS422物理接口UART通信协议UART设计波特率产生模块发送模块接收模块顶层模块串口驱动下载
通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART。可以实现全双工接收发送,是异步串行通信的总称,不表示具体的协议。RS232、RS422、RS485等都属于UART,只是它们的接口协议、电气特性、传输速率和机械结构不同而已。
RS232是电子工业协会(Electronic Industries Association,EIA) 制定的异步传输标准接口,同时对应着电平标准和通信协议(时序),其电平标准:+3V~+15V对应0,-3V~-15V对应1。RS232 的逻辑电平和TTL不一样但是协议一样。
RS485是一种串口接口标准,为了长距离传输采用差分方式传输,传输的是差分信号,抗干扰能力比RS232强很多。两线压差为-(2~6)V表示0,两线压差为+(2~6)V表示1。
EIA-422(过去称为RS-422)是一系列的规定采用4线,全双工,差分传输,多点通信的数据传输协议。它采用平衡传输——单向/非可逆,有使能端或没有使能端的传输线。和RS-485不同的是EIA-422不允许出现多个发送端而只能有多个接受端。硬件构成上EIA-422 (RS-422)相当于两组EIA-485(RS-485),即两个半双工的EIA-485(RS-485)构成一个全双工的EIA-422(RS-422)。
小编总结了这几种接口之间的区别如下表
名称 | RS232 | RS485 | RS422 |
---|---|---|---|
电平 | (+5~+15V) | -7~+12V | -7~+7V |
速率 | 20Kbps | 10Mbps | 10Mbps |
抗干扰性 | 抗噪声干扰性弱 | 抗干扰性强(差分传输) | 抗干扰性强(差分传输) |
传输距离 | 不超过50米 | 3000米 | 3000米 |
工作模式 | 全双工 | 半双工 | 全双工 |
参考链接?:https://blog.csdn.net/m0_38106923/article/details/98615747?ops_request_misc=&request_id=&biz_id=102&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-3
参考链接?:https://blog.csdn.net/Bertfans/article/details/80027151?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522158823917419725256756927%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.57652%2522%257D&request_id=158823917419725256756927&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-3
UART通信的一帧一般由11到12位数据组成。1bit的起始位,检测为低电平表示数据开始传输;紧接着8bits的数据;然后是1bit的奇偶校验位,可以是奇校验或者偶校验;最后是1bit或2bits的停止位,必须为高电平,表示一个字符数据的传输结束。 波特率:此参数容易和比特率混淆,其实他们是有区别的。具体可以百度更清楚。但是我认为uart中的波特率就可以认为是比特率,即每秒传输的位数(bit)。一般选波特率都会有9600,19200,115200等选项。其实意思就是每秒传输这么多个比特位数(bit)。
串口通信控制器的Verilog HDL实现(二) 波特率发生器模块
串口通信控制器的Verilog HDL实现(三) 发送模块的Verilog HDL 实现
串口通信控制器的Verilog HDL实现(四) 接收模块的Verilog HDL 实现
波波特率表示数据传输的速率,单位bps,表示位每秒。比如9600bps就表示1s可以传输9600bits的数据。异步收发没有时钟打拍来控制数据的传输,就需要保证收发双方在波特率设置上的一致。确保接收数据的完整性。波特率发生器实际上是一个分频器,从给定的系统时钟频率得到要求的波特率。一般来讲,为了提高系统的容错性处理,要求波特率发生器的输出时钟为实际串口数据波特率的N倍,N可以取值为8、16、32、64等。在本设计中,取N为16,因此波特率发生器的输出号频率应改为9600*16=153.6kbps。由于串口速率较低,其16倍频率值也不高,因此在设计中,可以不要求波特率发生器输出信号的占空比为50%,在本例中,其占空比为1:325。设计中的波特率发生器的代码(baud_gen.v)如下所列。
module baud_gen(
clk_50MHz,rst_p,bclk
);
input clk_50MHz;
input rst_p;
output bclk;//153.60kbps
reg bclk;
reg [8:0]cnt;//50000000/153600=325.5
always @(posedge clk_50MHz)
begin
if(rst_p)
begin
cnt<=0;
bclk<=0;
end
else
begin
if(cnt>324)
begin
cnt<=0;
bclk<=1;
end
else
begin
cnt<=cnt+1;
bclk<=0;
end
end
end
endmodule
由于波特率发生器产生的时钟信号bclk的频率为9600Hz的16倍,因此在发送器中,每16个bclk周期发送一个有效比特,发送数据格式严格按照串口数据帧来完成:首先是起始位(发送端口txd从逻辑1转化为逻辑0,并持续1/9600s),其次是8个有效数据比特(低位在前,高位在后),最后是一位停止位(没有添加校验位)。
module uart_tx(bclk,reset,tx_din,tx_cmd,tx_ready,txd);
input bclk;
input reset;
input [7:0]tx_din;
input tx_cmd;
output tx_ready;
output txd;
reg tx_ready;
parameter Lframe=8;
parameter [2:0]s_idle=3'b000;
parameter [2:0]s_start=3'b001;
parameter [2:0]s_wait=3'b010;
parameter [2:0]s_shift=3'b011;
parameter [2:0]s_stop=3'b100;
reg [2:0]state=s_idle;
reg [3:0]cnt=0;
reg [3:0]dcnt=0;
reg txdt;
assign txd=txdt;
always @(posedge bclk or posedge reset)
begin
if(reset)
begin
state<=s_idle;
cnt<=0;
tx_ready<=0;
txdt<=1'b1;
end
else
begin
case(state)
s_idle:
begin
tx_ready<=1;
cnt<=0;
txdt<=1'b1;
if(tx_cmd==1'b1)
state<=s_start;
else
state<=s_idle;
end
s_start:
begin
tx_ready<=1'b0;
txdt<=1'b0;//the start bit
state<=s_wait;
end
s_wait:
begin
tx_ready<=1'b0;
if(cnt>=4'b1110)
begin
cnt<=0;
if(dcnt==Lframe)
begin
state<=s_stop;
txdt<=1'b1;
dcnt<=0;
end
else
begin
state<=s_shift;
txdt<=txdt;
end
end
else
begin
state<=s_shift;
cnt<=cnt+1;
end
end
s_shift:
begin
tx_ready<=1'b0;
txdt<=tx_din[dcnt];
dcnt<=dcnt+1;
state<=s_wait;
end
s_stop:
begin
txdt<=1'b1;
if(cnt>4'b1110)
begin
tx_ready<=1'b1;
cnt<=0;
state<=s_idle;
end
else
begin
state<=s_stop;
cnt<=cnt+1;
end
end
endcase
end
end
endmodule
在接收系统中,起始状态和数据都需要依靠接收端检测得到,为了避免毛刺影响,能够得到正确的起始信号和有效数据,需要完成一个简单的最大似然判决,其方法如下:由于bclk信号的频率为9600Hz的16倍,则对于每个数据都会有16个样值,最终的采样比特值为出现次数超过8次的电平逻辑值。
module uart_rx(bclk,reset,rxd,rx_ready,rx_dout);
input bclk;
input reset;
input rxd;
output rx_ready;
output [7:0]rx_dout;
parameter [3:0]Lframe=9;
parameter [2:0]s_idle=3'b000;
parameter [2:0]s_sample=3'b010;
parameter [2:0]s_stop=3'b100;
reg rx_ready;
reg [7:0]rx_doutmp=0;
reg [2:0]state=s_idle;
reg [3:0]cnt=0;
reg [3:0]dcnt=0;
reg [3:0]num=0;
assign rx_dout=rx_doutmp;
always @(posedge bclk or posedge reset)
begin
if(reset==1'b1)
begin
state<=s_idle;
cnt<=0;
dcnt<=0;
num<=0;
rx_doutmp<=0;
rx_ready<=0;
end
else
begin
case(state)
s_idle:
begin
rx_dout<=0;
rx_ready<=1;
dcnt<=0;
if(cnt==4'b1111)
begin
cnt<=0;
if(num>7)
begin
state<=s_sample;
num<=0;
end
else
begin
state<=s_idle;
num<=0;
end
end
else
begin
cnt<=cnt+1;
if(rxd==1'b0)
begin
num<=num+1;
end
else
begin
num<=num;
end
end
end
s_sample:
begin
rx_ready<=1'b0;
if(dcnt==Lframe)
begin
state<=s_stop;
end
else
begin
if(cnt==4'b1111)
begin
dcnt<=dcnt+1;
cnt<=0;
if(num>7)
begin
num<=0;
rx_doutmp[dcnt]<=1;
end
else
begin
num<=0;
rx_doutmp[dcnt]<=0;
end
end
else
begin
cnt<=cnt+1;
if(rxd==1'b1)
begin
num<=num+1;
end
else
begin
num<=num;
end
end
end
end
s_stop:
begin
rx_ready<=1'b1;
if(cnt==4'b1111)
begin
cnt<=0;
state<=s_idle;
end
else
begin
cnt<=cnt+1;
end
end
endcase
end
end
endmodule
将上面三个模块连接起来即可。
module uart_top(sys_clk_50MHz,rst_p,txd,rxd,LED,button_n,button_s);
baud_gen u1(
.clk_50MHz(sys_clk_50MHz),
.rst_p(rst_p),
.bclk(bclk)
);
uart_tx u2(
.bclk(bclk),
.reset(rst_p),
.tx_din(din),
.tx_cmd(tx_cmd),
.tx_ready(tx_ready),
.txd(txd)
);
uart_rx u3(
.bclk(bclk),
.reset(rst_p),
.rxd(rxd),
.rx_out(rx_out),
.rx_ready(rx_ready)
);
endmodule
至此,小编讲解已经完成。