概述
协议篇(1)UART232串口verilog实现
- 零. 协议基本内容
- 一、UART简介
- 二、UART的通信协议和传输时序
- 三. 收发数据的波特率:
- verilog 实现(米联客代码)
- //发送部分
- //接收部分
- 仿真
零. 协议基本内容
- 学习VC 串口编程,了解串口协议的标准是必须的,其实串口相对于其它接口(如USB接口)是非常简单的。
RS232串口标准是美国EIA(电子工业联合会)与BELL等公司一起开发的通信协议。它适合于数据传输速率在0~20000bit/s范围内通信。RS232作为一种标准,被广泛应用于计算机与外设间的一种常通信接口,其中外设应用种类繁多,如:打印机、数据采集模块、测试装置和各种控制回路,甚至RS232串行接口还可用于计算机之间的简单连接上。
RS232串行接口的特点:RS232 DB-9 针串口引脚定义
应用广泛,几乎每台计算机都有一个或多个RS232串行接口,虽然最新的计算机出现了更多的USB这样的串行接口,但是RS232串行接口可以做很多USB无法进行的工作,而且RS232串行接口的开发难度以USB接口要简单得多。对于一些没有RS232串行接口的笔记本电脑,可以用USB-RS232转换线来连接RS232串口设备。
连接距离可达50100英尺,而USB连接最长为16英尺,PC机的并行打印机接口的连接距离最长为1015英尺。
对于双向连接,最少只需要3条导线,而并行连接一般最少也需要8条数据线。
一、UART简介
UART是一种通用串行数据总线,用于异步通信。该总线双向通信,实现全双工传输和接收。
二、UART的通信协议和传输时序
UART 通信 UART 首先将接收到的并行数据转换成串行数据来传输。消息帧从一个低位起始位开始,后面是 7 个或 8 个数据位,一个可用的奇偶位和一个或几个高位停止位。接收器发现开始位时它就知道数据准备发送,并尝试与发送器时钟频率同步。如果选择了奇偶校验,UART 就在数据位后面加上奇偶位。奇偶位可用来帮助错误校验。在接收过程中,UART 从消息帧中去掉起始位和结束位,对进来的字节进行奇偶校验,并将数据字节从串行转换成并行。
UART 传输时序如下图所示:
起始位:先发出一个逻辑”0”的信号,表示传输字符的开始。
数据位:从最低位开始传送,靠时钟定位。
奇偶校验位:资料位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验资料传送的正确性。
停止位:它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。 由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。
空闲位:处于逻辑“1”状态,表示当前线路上没有资料传送。
三. 收发数据的波特率:
RS-232接口不允许你随意使用数据传输速率,它有几个固定的速率,我们用baud来表示:
1200 bauds;
9600 bauds;
38400 bauds;
115200 bauds;(通常能达到的最高速率)
可见,最高的波特率很低,还不到1Mbps,属于低速度串口。
假如波特率为115200bauds,这样每一位持续时间为: (1/115200) = 8.7µs. 发送一个字节的数据,需要时间:8 x 8.7µs = 69µs;
由于还需要算上起始位和结束位,那么实际就需要时间:10 x 8.7µs = 87µs.这样发送数据最快的速度为:1s/87us = 11.5kbytes/s。
当然结束位可以为1.5位,也可以为2位,还可以有校验位,这样的话,数据速度就会更低了。
简单来说只有两根收发线,没有随行的时钟,时钟都是有本机自带去控制。
verilog 实现(米联客代码)
//发送部分
module UART232_TX #(
parameter BAUD_DIV = 14'd10416 //波特率时钟,9600bps,100Mhz/9600=10416,波特率可调
)
(
input clk_i, //100M时钟
input [7:0] uart_tx_data_i, //待发送数据
input uart_tx_en_i, //发送发送使能信号
output uart_tx_o //串口输出
);
parameter BAUD_DIV_CAP = BAUD_DIV / 2; //波特率时钟中间采样点,100Mhz/9600/2=5208,波特率可调
//-------------------------串口计数,中值采样----------------------
reg [13:0] baud_div=0; //波特率设置计数器
reg baud_bps=0; //数据发送点信号,高有效
reg uart_send_flag=0; //数据发送标志位
always@(posedge clk_i)
begin
if(baud_div==BAUD_DIV_CAP) //当波特率计数器计数到数据发送中点时,产生采样信号baud_bps,用来发送数据
begin
baud_bps<=1'b1;
baud_div<=baud_div+1'b1;
end
else if(baud_div<BAUD_DIV && uart_send_flag)//数据发送标志位有效期间,波特率计数器累加,以产生波特率时钟
begin
baud_div<=baud_div+1'b1;
baud_bps<=0;
end
else
begin
baud_bps<=0;
baud_div<=0;
end
end
//------------------------生成串口发送标志位,串口数据加载与卸载--------------------------
reg [9:0] send_data=10'b1111111111;//待发送数据寄存器,1bit起始信号+8bit有效信号+1bit结束信号
reg [3:0] bit_num=0; //发送数据个数计数器
reg uart_tx_o_r=1; //发送数据寄存器,初始状态位高
always@(posedge clk_i)
begin
if(uart_tx_en_i) //接收数据发送使能信号时,产生数据发送标志信号
begin
uart_send_flag<=1'b1;
send_data<={1'b1,uart_tx_data_i,1'b0};//待发送数据寄存器装填,1bit起始信号0+8bit有效信号+1bit结束信号
end
else if(bit_num==4'd10) //发送结束时候,清楚发送标志信号,并清楚待发送数据寄存器内部信号
begin
uart_send_flag<=1'b0;
send_data<=10'b1111_1111_11;
end
end
//-------------------------串口数据发送----------------------------
always@(posedge clk_i)
begin
if(uart_send_flag) //发送有效时候
begin
if(baud_bps)//检测发送点信号
begin
if(bit_num<=4'd9)
begin
uart_tx_o_r<=send_data[bit_num]; //发送待发送寄存器内数据,从低位到高位
bit_num<=bit_num+1'b1;
end
end
else if(bit_num==4'd10)
bit_num<=4'd0;
end
else
begin
uart_tx_o_r<=1'b1; //空闲状态时,保持发送端位高电平,以备发送时候产生低电平信号
bit_num<=0;
end
end
assign uart_tx_o=uart_tx_o_r;
endmodule
//接收部分
module UART232_RX #(
parameter [13:0] BAUD_DIV = 14'd10416 //波特率时钟,9600bps,100Mhz/9600=10416
)
(
input clk_i,
input uart_rx_i,
output [7:0] uart_rx_data_o,
output uart_rx_done,
output baud_bps_tb //for simulation
);
parameter BAUD_DIV_CAP = BAUD_DIV /2;//波特率时钟中间采样点,100Mhz/9600/2=5208
//------------------------计数控制-------------------------------
reg [13:0] baud_div=0; //波特率设置计数器
reg baud_bps=0; //数据采样点信号
reg bps_start=0; //波特率启动标志
always@(posedge clk_i)
begin
if(baud_div==BAUD_DIV_CAP) //当波特率计数器计数到采样点时,产生采样信号baud_bps
begin
baud_bps<=1'b1;
baud_div<=baud_div+1'b1;
end
else if(baud_div<BAUD_DIV && bps_start) //当波特率计数器启动时,计数器累加
begin
baud_div<=baud_div+1'b1;
baud_bps<=0;
end
else
begin
baud_bps<=0;
baud_div<=0;
end
end
//--------------------通过低电平判断是否有数据输入---------------------
reg [4:0] uart_rx_i_r=5'b11111; //数据接收缓存器
always@(posedge clk_i)
begin
uart_rx_i_r<={uart_rx_i_r[3:0],uart_rx_i};
end
//数据接收缓存器,当连续接收到五个低电平时,即uart_rx_int=0时,作为接收到起始信号
wire uart_rx_int=uart_rx_i_r[4] | uart_rx_i_r[3] | uart_rx_i_r[2] | uart_rx_i_r[1] | uart_rx_i_r[0];
//------------------------数据接收----------------------------------------
reg [3:0] bit_num=0; //接收数据个数计数器
reg uart_rx_done_r=0; //数据接收完成寄存器
reg state=1'b0;
reg [7:0] uart_rx_data_o_r0=0;//数据接收过程中,数据缓存器
reg [7:0] uart_rx_data_o_r1=0;//数据接收完成,数据寄存器
always@(posedge clk_i)
begin
uart_rx_done_r<=1'b0;
case(state)
1'b0 :
if(!uart_rx_int)//当连续接收到五个低电平时,即uart_rx_int=0时,作为接收到起始信号,启动波特率时钟
begin
bps_start<=1'b1;
state<=1'b1;
end
1'b1 :
if(baud_bps) //每次等待波特率采样中心时,接收数据,放入数据缓存器中
begin
bit_num<=bit_num+1'b1;
if(bit_num<4'd9) //接收1bit起始信号,8bit有效信号,1bit结束信号
uart_rx_data_o_r0[bit_num-1]<=uart_rx_i;
end
else if(bit_num==4'd10) //接收完成时候,接收数据个数计数器清零,产生接收完成标志位,并将数据写入数据寄存器,关闭波特率时候
begin
bit_num<=0;
uart_rx_done_r<=1'b1;
uart_rx_data_o_r1<=uart_rx_data_o_r0;
state<=1'b0;//进入状态0,再次循环检测
bps_start<=0;
end
default:;
endcase
end
assign baud_bps_tb=baud_bps;//for simulation
assign uart_rx_data_o=uart_rx_data_o_r1;
assign uart_rx_done=uart_rx_done_r;
endmodule
仿真
注意:使用中看好自己时钟,根据时钟和波特率算好参数直接带入就可以了
最后
以上就是要减肥世界为你收集整理的协议篇(1)UART232串口verilog实现的全部内容,希望文章能够帮你解决协议篇(1)UART232串口verilog实现所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复