赞
踩
目录
RS232 通信接口标准,通用异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART)是一种异步收发传输器,其在数据发送时将并行数据转换成串行数据来传输,在数据接收时将接收到的串行数据转换成并行数据,可以实现全双工传输和接收。
UART 是异步串行通信的总称(UART 是一种协议)。而 RS232、RS449、RS423、RS422 和 RS485 等,是对应各种异步串行通信口的接口标准和总线标准,它们规定了通信口的电气特性、传输速率、连接特性和接口的机械特性等内容。若系统存在多个 UART接口,则可分别称为 COM1、COM2 等。
RS-232 是美国电子工业联盟(EIA)制定的串行数据通信的接口标准,原始编号全称是 EIA-RS-232(简称 232,RS232),被广泛用于计算机串行接口外设连接。
DB9 接口的针脚定义如图:
通常使用RXD、TXD、GND这三个信号
UART 通信在使用前需要做多项设置,最常见的设置包括数据位数、波特率大小、奇偶校验类型和停止位数。
数据位(Data bits):该参数定义单个 UART 数据传输在开始到停止期间发送的数据位数。可选择为:5、6、7 或者 8(默认)。
波特率(Baud):是指从一设备发到另一设备的波特率,即每秒钟可以通信的数据比特个数。典型的波特率有 300, 1200, 2400, 9600, 19200, 115200 等。一般通信两端设备都要设为相同的波特率,但有些设备也可设置为自动检测波特率。通俗的说,就是一个数据的高电平/低电平持续的时间,是一个最基本的时间单位。
串口全部都是使用的二进制,所以波特率就是比特率。
奇偶校验类型(Parity Type):是用来验证数据的正确性。奇偶校验一般不使用,如果使用,则既可以做奇校验(Odd)也可以做偶校验(Even)。在偶校验中,因为奇偶校验位会被相应的置 1 或 0(一般是最高位或最低位),所以数据会被改变以使得所有传送的数位(含字符的各数位和校验位)中“1”的个数为偶数;在奇校验中,所有传送的数位(含字符的各数位和校验位)中“1”的个数为奇数。奇偶校验可以用于接受方检查传输是否发送生错误,如果某一字节中“1”的个数发生了错误,那么这个字节在传输中一定有错误发生。如果奇偶校验是正确的,那么要么没有发生错误,要么发生了偶数个的错误。如果用户选择数据长度为 8 位,则因为没有多余的比特可被用来作为奇偶校验位,因此就叫做“无奇偶校验(Non)”。
停止位(Stop bits):在每个字节的数据位发送完成之后,发送停止位,来标志着一次数据传输完成,同时用来帮助接受信号方硬件重同步。可选择为:1(默认)、1.5 或者 2 位。
1.首先应该定义一个分频计数器(波特率的产生)
2.定义一个位计数器(用来控制每一位去做什么)
3.定义一个1S的延时计数器(用来推迟1S发送)
4.实现位实现逻辑(定义每一位具体做什么)
5.实现Led翻转逻辑(每完成一次发送就翻转一次)
(底层通用模块)
- module uart_byte_tx(
- Clk,
- Reset_n,
- Data,
- Send_Go,
- Baud_set,
- uart_tx,
- Tx_done
- );
- input Clk;
- input Reset_n;
- input [7:0]Data;
- input Send_Go;
- input [2:0]Baud_set;
- output reg uart_tx;
- output reg Tx_done;
-
- //Baud_set = 0 就让波特率 = 9600;
- //Baud_set = 1 就让波特率 = 19200
- //Baud_set = 2 就让波特率 = 38400;
- //Baud_set = 3 就让波特率 = 57600;
- //Baud_set = 4 就让波特率 = 115200;
-
- reg [17:0]bps_DR;
- always@(*)
- case(Baud_set)
- 0:bps_DR = 1000000000/9600/20;
- 1:bps_DR = 1000000000/19200/20;
- 2:bps_DR = 1000000000/38400/20;
- 3:bps_DR = 1000000000/57600/20;
- 4:bps_DR = 1000000000/115200/20;
- default:bps_DR = 1000000000/9600/20;
- endcase
-
- reg Send_en;
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- Send_en <= 0;
- else if(Send_Go)
- Send_en <= 1;
- else if(Tx_done)
- Send_en <= 0;
-
- reg [7:0]r_Data;
- always@(posedge Clk)
- if(Send_Go)
- r_Data <= Data;
- else
- r_Data <= r_Data;
-
- reg [17:0]div_cnt;
- wire bps_clk;
- assign bps_clk = (div_cnt == 1);//用上升沿的脉冲来计数
-
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- div_cnt <= 0;
- else if(Send_en)begin
- if(div_cnt == bps_DR - 1)
- div_cnt <= 0;
- else
- div_cnt <= div_cnt + 1'b1;
- end
- else
- div_cnt <= 0;
- reg [3:0]bps_cnt;
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- bps_cnt <= 0;
- else if(Send_en)begin
- if(bps_clk)begin//这是以刚开始计数作为位计数的触发,所以应该是11,而不是9
- if(bps_cnt == 11)
- bps_cnt <= 0;
- else
- bps_cnt <= bps_cnt + 1'b1;
- end
- end
- else
- bps_cnt <= 0;
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n) begin
- uart_tx <= 1'b1;
- end
- else begin
- case(bps_cnt)
- 1:uart_tx <= 0;//起始位
- 2:uart_tx <= r_Data[0];
- 3:uart_tx <= r_Data[1];
- 4:uart_tx <= r_Data[2];
- 5:uart_tx <= r_Data[3];
- 6:uart_tx <= r_Data[4];
- 7:uart_tx <= r_Data[5];
- 8:uart_tx <= r_Data[6];
- 9:uart_tx <= r_Data[7];
- 10:uart_tx <= 1;//停止位
- 11:begin uart_tx <= 1;end
- default:uart_tx <= 1;
- endcase
- end
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- Tx_done <= 0;
- else if((bps_clk == 1) && (bps_cnt == 10))
- Tx_done <= 1;
- else
- Tx_done <= 0;
- endmodule

顶层调用文件
- module uart_tx_test(
- Clk,
- Reset_n,
- uart_tx,
- Led,//Led作为输出
- Data
- );
- input Clk;
- input Reset_n;
- input [7:0]Data;//对应7位拨码开关的值
- output uart_tx;
- output reg Led;
-
-
- reg Send_Go;//产生的脉冲信号
- wire Tx_done;
-
- uart_byte_tx uart_byte_tx( //将底层通用模块例化进来
- .Clk(Clk),
- .Reset_n(Reset_n),
- .Data(Data),
- .Send_Go(Send_Go),
- .Baud_set(3'd4),
- .uart_tx(uart_tx),
- .Tx_done(Tx_done)
- );
- //1s一次
- parameter Dly_cnt = 50000000-1;
-
- reg [24:0]counter;//定时1S计数器
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- counter <= 0;
- else if(counter == Dly_cnt)
- counter <= 0;
- else
- counter <= counter + 1;
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- Send_Go <= 0;
- else if(counter == 1)
- Send_Go <= 1;
- else
- Send_Go <= 0;//因为是脉冲信号而不是电平信号,所以它的值只关心什么时候产生高脉冲,其他不关心。
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- Led <= 0;
- else if(Tx_done)
- Led <= !Led;//每当发完一次就翻转
- else
- Led <= Led;
-
-
- endmodule

1.复制端口声明,例化连接,ctrl可以实现列编辑,在端口名前加点。
2.复制输入端口,直接将input替换成reg。在vivado中,单击鼠标右键,选择replace in files,可以选择设计文件/仿真文件的替换 。
- `timescale 1ns / 1ns
-
- module uart_byte_tb();
-
- reg Clk;
- reg Reset_n;
- reg [7:0]SW;
- wire uart_tx;
- wire Led;
-
- uart_byte_tx uart_byte_tx (
- .Clk(Clk),
- .Reset_n(Reset_n),
- .SW(SW),
- .uart_tx(uart_tx),
- .Led(Led)
- );
-
- defparam uart_byte_tx.MCNT_DLY = 500000-1;//更改空闲时间
-
- initial Clk = 1;
- always #10 Clk =~Clk;
-
- initial begin
- Reset_n = 0;
- #201;
- Reset_n =1;
- SW = 8'b0101_0101;
- #30000000;
- SW = 8'b1010_1010;
- #30000000;
- $stop;
- end
- endmodule

- module uart_byte_tx(
- Clk,
- Reset_n,
- Data,
- Send_Go,
- Baud_set,
- uart_tx,
- Tx_done
- );
- input Clk;
- input Reset_n;
- input [7:0]Data;
- input Send_Go;
- input [2:0]Baud_set;
- output reg uart_tx;
- output reg Tx_done;
-
- //Baud_set = 0 就让波特率 = 9600;
- //Baud_set = 1 就让波特率 = 19200
- //Baud_set = 2 就让波特率 = 38400;
- //Baud_set = 3 就让波特率 = 57600;
- //Baud_set = 4 就让波特率 = 115200;
-
- reg [17:0]bps_DR;
- always@(*)
- case(Baud_set)
- 0:bps_DR = 1000000000/9600/20;
- 1:bps_DR = 1000000000/19200/20;
- 2:bps_DR = 1000000000/38400/20;
- 3:bps_DR = 1000000000/57600/20;
- 4:bps_DR = 1000000000/115200/20;
- default:bps_DR = 1000000000/9600/20;
- endcase
-
- reg Send_en;
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- Send_en <= 0;
- else if(Send_Go)
- Send_en <= 1;
- else if(Tx_done)
- Send_en <= 0;
-
- reg [7:0]r_Data;
- always@(posedge Clk)
- if(Send_Go)
- r_Data <= Data;
- else
- r_Data <= r_Data;
-
- reg [17:0]div_cnt;
- wire bps_clk;
- assign bps_clk = (div_cnt == 1);//用上升沿的脉冲来计数
-
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- div_cnt <= 0;
- else if(Send_en)begin
- if(div_cnt == bps_DR - 1)
- div_cnt <= 0;
- else
- div_cnt <= div_cnt + 1'b1;
- end
- else
- div_cnt <= 0;
- reg [3:0]bps_cnt;
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- bps_cnt <= 0;
- else if(Send_en)begin
- if(bps_clk)begin//这是以刚开始计数作为位计数的触发,所以应该是11,而不是9
- if(bps_cnt == 11)
- bps_cnt <= 0;
- else
- bps_cnt <= bps_cnt + 1'b1;
- end
- end
- else
- bps_cnt <= 0;
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n) begin
- uart_tx <= 1'b1;
- end
- else begin
- case(bps_cnt)
- 1:uart_tx <= 0;//起始位
- 2:uart_tx <= r_Data[0];
- 3:uart_tx <= r_Data[1];
- 4:uart_tx <= r_Data[2];
- 5:uart_tx <= r_Data[3];
- 6:uart_tx <= r_Data[4];
- 7:uart_tx <= r_Data[5];
- 8:uart_tx <= r_Data[6];
- 9:uart_tx <= r_Data[7];
- 10:uart_tx <= 1;//停止位
- 11:begin uart_tx <= 1;end
- default:uart_tx <= 1;
- endcase
- end
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- Tx_done <= 0;
- else if((bps_clk == 1) && (bps_cnt == 10))
- Tx_done <= 1;
- else
- Tx_done <= 0;
- endmodule

- module uart_tx_test(
- Clk,
- Reset_n,
- uart_tx,
- );
- input Clk;
- input Reset_n;
- output uart_tx;
- output reg Led;
-
-
- reg Send_Go;//产生的脉冲信号
- wire Tx_done;
- reg [7:0]Data;
-
- uart_byte_tx uart_byte_tx( //将底层通用模块例化进来
- .Clk(Clk),
- .Reset_n(Reset_n),
- .Data(Data),
- .Send_Go(Send_Go),
- .Baud_set(3'd4),
- .uart_tx(uart_tx),
- .Tx_done(Tx_done)
- );
- //1s一次
- parameter Dly_cnt = 50000000-1;
-
- reg [24:0]counter;//定时1S计数器
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- counter <= 0;
- else if(counter == Dly_cnt)
- counter <= 0;
- else
- counter <= counter + 1;
-
- always@(posedge Clk or negedge Reset_n)
- if(!Reset_n)
- Send_Go <= 0;
- else if(counter == 1)
- Send_Go <= 1;
- else
- Send_Go <= 0;//因为是脉冲信号而不是电平信号,所以它的值只关心什么时候产生高脉冲,其他不关心。
-
- endmodule

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。