UART串口通信协议
前言
UART通信协议:
当检测到输入信号的下降沿时开始数据传输,同时传输数据每次不超过8位不低于5位,当数据传输结束时将电平拉高作为停止位通常为1,1.5或2位。
标识态:
在1个字符开始传输前,输出线必须在逻辑上处于“1”状态,这称为标识态。
起始位:
传输一开始,输出线由标识态变为“0”状态,从而作为起始位。
数据位:
起始位后面为5~8个信息位,信息位由低往高排列,即先传字符的低位,后传字符的高位。
奇偶校验位:
信息位后面为校验位,校验位可以按奇校验设置,也可以按偶校验设置,或不设校验位。
按位异或,若结果为1则将奇偶校验位赋值为1,若结果为0则将奇偶校验位赋值为0
奇校验:1000110-------->1000110(0)
偶校验:1000110-------->1000110(1)
停止位:
最后是逻辑的“1”作为停止位,停止位可为1位、1.5位或者2位
注:如果传输完1个字符以后,立即传输下一个字符,那么,后一个字符的起始位便紧挨着前一个字符的停止位了,否则,输出线又会进入标识态。
一、RS232协议
UART即通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),一般计算机外设的UART使用的协议是RS-232-C。RS-232-C是美国电子工业协会EIA(Electronic Industry Association)制定的一种串行物理接口标准。通常 RS-232 接口以9个接脚 (DB-9) 或是25个接脚 (DB-25) 的型态出现。接头分为公头和母头两种,只有公头和母头配对才能连接。
二、设计思路
1.设计流程图
外设结构
代码设计结构
RX模块
RX模块代码实现:
`timescale 1ns / 1ps
module rx(
input clk ,//系统时钟
input rst_n ,//复位按键
input rx ,//输入信号
output reg[7:0] data_reg ,//输出数据
output reg done //握手信号
);
parameter CLK = 50_000_000,//系统时钟频率
BPS = 9600, //波特率
DELAY = CLK / BPS;
parameter check = 0; //奇偶性 0为偶 1为奇
reg [31:0] cnt_bps;
reg [3:0] cnt_bit;
reg [8:0] data;
reg check_bit;
reg en_rx;
reg reg01;
reg reg02;
wire flag;
//——————————negedge————————————————//
always@(posedge clk)//检测下降沿
if(!rst_n)
begin
reg01 <= 0;
reg02 <= 0;
end
else
begin
reg01 <= rx;
reg02 <= reg01;
end
assign flag = (~reg01) & (reg02);
//——————————energy——————————————//
always@(posedge clk)//使能信号
if(!rst_n)
en_rx <= 0;
else if(flag == 1)//触发输入时使能信号拉高
en_rx <= 1;
else if(cnt_bit == 10 && cnt_bps == (DELAY)/2 - 1)//当数据传输完毕使能信号归零
en_rx <= 0;
//——————————count of BPS————————————//
always@(posedge clk)//计算比特流
if(!rst_n)
cnt_bps <= 0;
else if(en_rx == 1)
begin
if(cnt_bps == (DELAY) - 1)
cnt_bps <= 0;
else
cnt_bps <= cnt_bps + 1;
end
else
cnt_bps <= 0;
//——————————count of bit——————————————//
always@(posedge clk)//计算传输数据位数
if(!rst_n)
cnt_bit <= 0;
else if(en_rx == 1)
begin
if(cnt_bps == (DELAY) - 1)
cnt_bit <= cnt_bit + 1;
end
else
cnt_bit <= 0;
//——————————get the data————————————————//
always@(posedge clk)//扫描数据
if(!rst_n)
data <= 0 ;
else if(cnt_bit > 0 && cnt_bit < 10 && en_rx == 1 && cnt_bps == (DELAY)/2)
data[cnt_bit - 1] <= reg02;
else if(en_rx == 1)
data <= data;
else
data <= 0;
//————————————check——————————————//
always@(posedge clk)//奇偶性检测
if(!rst_n)
check_bit <= 0;
else if(cnt_bit == 10 && cnt_bps == 20)
check_bit <= ^data;
//———————————check bit——————————————//
always@(posedge clk)//二级寄存器存入数据
if(!rst_n)
data_reg <= 0;
else if(cnt_bit == 10 && cnt_bps == (DELAY) / 3)
begin
if(check_bit == check)
data_reg <= data[7:0];
else
data_reg <= 0;
end
//——————————————done——————————————//
always@(posedge clk)//握手信号赋值
if(!rst_n)
done <= 0;
else if(cnt_bps == (DELAY) / 2 - 10 && cnt_bit ==10)
done <= 1;
else
done <= 0;
endmodule
TX模块
TX模块代码实现:
`timescale 1ns / 1ps
module tx(
input clk ,
input rst_n ,
input done ,
input [7:0] data_reg,//输入数据
output reg tx //输出信号
);
parameter CLK = 50_000_000,
BPS = 9600,
DELAY = CLK / BPS;
parameter check = 0;
reg [31:0] cnt_bps;
reg [3:0] cnt_bit;
reg en_tx;
reg [7:0] data;
//——————————data—————————————//
always@(posedge clk)
if(!rst_n)
data <= 0;
else if(done == 1)
data <= data_reg;
//——————————energy————————————//
always@(posedge clk)
if(!rst_n)
en_tx <= 0;
else if(done == 1)
en_tx <= 1;
else if(cnt_bit == 10 && cnt_bps == (DELAY)/2 - 1)
en_tx <= 0;
//----------count of BPS------------//
always@(posedge clk)
if(!rst_n)
cnt_bps <= 0;
else if(en_tx == 1)
begin
if(cnt_bps == (DELAY) - 1)
cnt_bps <= 0;
else
cnt_bps <= cnt_bps + 1;
end
else
cnt_bps <= 0;
//----------count of bit--------------//
always@(posedge clk)
if(!rst_n)
cnt_bit <= 0;
else if(en_tx == 1)
begin
if(cnt_bps == (DELAY) - 1)
cnt_bit <= cnt_bit + 1;
end
else
cnt_bit <= 0;
//————————————————————//
always@(posedge clk)//tx赋值
if(!rst_n)
tx <= 1;
else if(en_tx == 1 && cnt_bit > 0 && cnt_bit < 9)
tx <= data[cnt_bit - 1];
else if(en_tx == 1 && cnt_bit == 9)
tx <= (check)?(~(^data)):(^data);
else if(en_tx == 1 && cnt_bit == 0)
tx <= 0;
else if(en_tx == 1 && cnt_bit == 10)
tx <= 1;
else
tx <= 1;
endmodule
顶层模块
TOP模块代码如下(示例):
`timescale 1ns / 1ps
module TOP(
input clk ,
input rst_n ,
input rx ,
output tx
);
parameter sysclk = 50_000_000,
bps = 9600;
parameter check = 0; ///0 偶 1 奇
wire done;
wire [7:0] data_reg;
tx tx_u(
.clk (clk ),
.rst_n (rst_n ),
.done (done ),
.data_reg (data_reg ),
.tx (tx )
);
rx rx_u(
.clk (clk ),
.rst_n (rst_n ),
.rx (rx ),
.data_reg (data_reg ),
.done (done )
);
endmodule
2.实验结果
串口调试工具页面如下:
发送区为输入数据,接收区为传输到PC端数据
总结
串口通信总结:
了解串口传输的基本应用场景,了解UART传输数据原理,能够合理设计模块使各个模块信号实现总体功能。
掌握基本通信协议;
掌握基本接口标准;
了解ADC/DAC接口标准;
了解信号处理原理;