3.EP4CE10F17的串口设计
前记:师夷长技以自强。
1.基本概念
UART:Universal Asynchronous Receiver/Transmitter,通用异步收发传输器,它是一种电子器件,可以在数据发送时将并行数据转换成串行数据来传输,在数据接收时将接收到的串行数据转换成并行数据。UART是异步串行通信的总称,包含了RS232,RS449,RS423,RS422和RS485等协议标准。
RS-232:美国电子工业联盟(EIA)制定的串行数据通信的接口标准,被广泛用于计算机串行接口外设连接。
2.UART设计
2.1关键参数
我们已经知道UART是一种串行传输协议,那么一次传多少个数据呢?应该传多快呢?怎么区分一次传输?还有既然是通信,难免会有干扰,如何降低数据传输错误率呢?这些都是一个通信设计者应该考虑的事情。
数据位:定义单个UART数据传输从开始到停止期间发送的数据位数。可以为5,6,7,8(默认)。
波特率:每秒可以通信的数据比特个数,典型波特率有300,1200,2400,9600,19200,115200。
奇偶校验类型:可选参数,分为奇校验(各数位和校验位中“1”的个数为奇数)和偶校验(各数位和校验位中“1”的个数为偶数)。
停止位:每次传输完成后就要发送停止位,可选1,1.5,2位。
2.2时序
需要注意的是,UART作为一种古老的传输协议,是先传低位数据的。
2.3电路设计
早起采用的方案是RS232转TTL
但由于DB9的RS232接口占用PCB太大,多数系统采用USB转TTL
在windows下装CH340G的驱动程序就能够仿真标准串口了。
3.UART模块设计
3.1模块框图
为了启动UART发送数据,需要一个Send_En信号;发送完成应该输出Tx_Done信号;待发送的数据data_byte[7:0];波特率设置baud_Set[2:0];输出的信号有RS232_Tx;还有基本的时序信号Clk和Rst_n,uart_state。
3.2 代码文件
module UART(
input Clk,
input Rst_n,
input Send_En,
input [7:0]data_byte,
input [2:0]baud_set,
output uart_state,
output reg Tx_done,
output reg Rs232_Tx
);
reg en;
reg [7:0]r_data_byte;
reg [12:0]Clk_CNT;
reg [3:0]BPS_CNT;
reg [12:0]Clk_CNT_SHR;
always@(posedge Clk,negedge Rst_n)
if(!Rst_n)
en <= 0;
else if(Send_En)
en <= 1;
else if(Tx_done)
en <= 0;
else
en <= en;
always@(posedge Clk,negedge Rst_n)
if(!Rst_n)
r_data_byte <= 0;
else if(Send_En)
r_data_byte <= data_byte;
else
r_data_byte <= r_data_byte;
always@(posedge Clk,negedge Rst_n)
if(!Rst_n)
Clk_CNT_SHR <= 0;
else if(Send_En)begin
case(baud_set)
0:
Clk_CNT_SHR <= 5208; //9600
1:
Clk_CNT_SHR <= 3472; //14400
2:
Clk_CNT_SHR <= 2604; //19200
3:
Clk_CNT_SHR <= 1736; //28800
4:
Clk_CNT_SHR <= 1302; //38400
5:
Clk_CNT_SHR <= 892; //56000
6:
Clk_CNT_SHR <= 868; //57600
7:
Clk_CNT_SHR <= 434; //115200
default:;
endcase
end
else
Clk_CNT_SHR <= Clk_CNT_SHR;
always@(posedge Clk,negedge Rst_n)
if(!Rst_n)
Clk_CNT <= 0;
else if(en)
if(Clk_CNT == Clk_CNT_SHR)
Clk_CNT <= 0;
else
Clk_CNT <= Clk_CNT + 13'b1;
else
Clk_CNT <= 0;
always@(posedge Clk,negedge Rst_n)
if(!Rst_n)
BPS_CNT <= 0;
else if(en&&Clk_CNT == Clk_CNT_SHR)begin
if(BPS_CNT == 10)
BPS_CNT <= 0;
else
BPS_CNT <= BPS_CNT + 4'b1;
end
else if(Tx_done)
BPS_CNT <= 0;
else
BPS_CNT <= BPS_CNT;
always@(posedge Clk,negedge Rst_n)
if(!Rst_n)
Rs232_Tx <= 1;
else if(en)
case(BPS_CNT)
0:
Rs232_Tx <= 0;
1:
Rs232_Tx <= r_data_byte[0];
2:
Rs232_Tx <= r_data_byte[1];
3:
Rs232_Tx <= r_data_byte[2];
4:
Rs232_Tx <= r_data_byte[3];
5:
Rs232_Tx <= r_data_byte[4];
6:
Rs232_Tx <= r_data_byte[5];
7:
Rs232_Tx <= r_data_byte[6];
8:
Rs232_Tx <= r_data_byte[7];
9:
Rs232_Tx <= 1;
endcase
else
Rs232_Tx <= 1;
always@(posedge Clk,negedge Rst_n)
if(!Rst_n)
Tx_done <= 1;
else if(en&&BPS_CNT==10)
Tx_done <= 1;
else
Tx_done <= 0;
assign uart_state = en;
endmodule
3.3 仿真
3.3.1 仿真文件
为了测试UART的时序是否正确,需要进行RTL仿真,代码如下
`timescale 1ns/1ns
`define clock_period 20module UART_tb();
reg Clk;
reg Rst_n;
reg Send_En;
reg [7:0]data_byte;
reg [2:0]baud_set;
wire uart_state;
wire Tx_done;
wire Rs232_Tx;
UART UART1(
.Clk(Clk),
.Rst_n(Rst_n),
.Send_En(Send_En),
.data_byte(data_byte),
.baud_set(baud_set),
.uart_state(uart_state),
.Tx_done(Tx_done),
.Rs232_Tx(Rs232_Tx)
);
initial Clk = 0;
always #10 Clk = ~Clk;
initial begin
Rst_n = 0;
Send_En = 0;
#`clock_period;
Rst_n = 1;
data_byte = 8'h53;
baud_set = 0;
Send_En = 1;
#`clock_period;
Send_En =0;
wait(Tx_done);
#20000;
data_byte = 8'h73;
Send_En = 1;
#`clock_period;
Send_En =0;
wait(Tx_done);
#20000;
$stop;
end
endmodule
仿真的结果为
3.3.2 板上测试
为了在开发板上能跑起来,需要在写一个UART_top模块,主要的测试思路是固定波特率为9600,要发送的数据是0x54,复位后就不断的发送数据,添加的代码文件如下
module UART_top(
input Clk,
input Rst_n,
output Rs232_Tx
);
reg Send_En;
wire [7:0]data_byte;
wire [2:0]baud_set;
wire Tx_done;
UART UART1(
.Clk(Clk),
.Rst_n(Rst_n),
.Send_En(Send_En),
.data_byte(data_byte),
.baud_set(baud_set),
.uart_state(),
.Tx_done(Tx_done),
.Rs232_Tx(Rs232_Tx)
);
assign data_byte = 8'h54;
assign baud_set = 8'b0;
always@(posedge Clk,negedge Rst_n)
if(!Rst_n)
Send_En <= 0;
else if(Tx_done)
Send_En <= 1;
else
Send_En <= 0;
endmodule
为了确保设计的时序没问题,可以先在软件上仿真,所以需要添加的测试文件UART_top_tb如下
`timescale 1ns/1ns
module UART_top_tb();
reg Clk;
reg Rst_n;
wire Rs232_Tx;
UART_top UART_top1(
.Clk(Clk),
.Rst_n(Rst_n),
.Rs232_Tx(Rs232_Tx)
);
initial Clk = 0;
always #10 Clk = ~Clk;
initial begin
Rst_n = 0;
#20;
Rst_n = 1;
#10000000;
end
endmodule
仿真后可以得到如下的波形
下载到开发板上,用在PC端用串口调试助手接收也可以看到收到的数据
3.EP4CE10F17的串口设计相关推荐
- C#串口设计SerialPort类(维修电工Demo)
维修电工干久了,都不知道想干点啥? 写个串口助手吧, 0先做准备工作:ui的控件用 ComboBox 1引用命名空间 using System.IO.Ports;//引用命名空间 2 创建一个类对象 ...
- 百问网物联网实战-串口设计
一 串口介绍 对于串口初始化的流程,我们可以总结为4点: 1.使能串口外设时钟: 2.使能串口外设的GPIO的时钟: 3.配置串口外设GPIO的复用功能: 4.配置串口的参数:波特率.数据位.停止位. ...
- FPGA串口(UART)通信协议制定与设计思路详解示例
串口(UART)通信协议制定与设计思路详解 1 概述 本文用于描述规定的串口通信协议,以及传输内容. 2 项目关于串口的要求 a) 支持BIT自检,1路UART上报BIT信息: b) 1路UART接口 ...
- 【导纳分析】基于FPGA的导纳分析仪的verilog设计
1.软件版本 ISE14.7+ Modelsim SE-64 10.1c 2.本算法理论知识 3.核心代码 `timescale 1ns / 1ps // // Company: // Enginee ...
- serialport通过usb通讯_IOT串口通讯-RS232/RS485
串口 串口是串行接口(serial port)的简称,也称为串行通信接口或COM接口.串口通信是指采用串行通信协议(serial communication)在一条信号线上将数据一个比特一个比特地逐位 ...
- CH343芯片应用—硬件设计指南
CH343属于沁恒第三代USB转串口芯片系列的单串口型号,基于经典版CH340芯片完成技术革新,实现USB转高速异步串口,支持最高6Mbps串口波特率. 电源设计 CH343芯片有3个电源端分别是VD ...
- 嵌入式学习(四)——串口
目录 一.通信的基本概念 1.1 同步通信和异步通信 1.2 电平信号和差分信号 1.3 并行接口和串行接口 1.4 单工通信和双工通信 二.串口通信 2.1 基本概念 2.2 起始位.数据位.奇偶校 ...
- USB转52单片机下载串口的“转换芯片”MAX232与CH340G的区别
USB转52单片机下载串口的"转换芯片"MAX232与CH340G的区别:首先需要说明,单片机的下载口TXD.RXD(P3.0与P3.1)是TTL电平(TTL电平是正逻辑数据表示, ...
- CH9101芯片应用—硬件设计指南
CH9101芯片属于沁恒第三代USB转串口芯片系列的单串口型号,基于经典版CH340芯片完成技术革新,实现USB转高速异步串口,支持最高6Mbps串口波特率.CH9101提供了5种封装,CH9101U ...
最新文章
- oracle 提示:ORA-02292:integrity constraint(xxxxxxx) violated - child record found
- 面试Android实习生
- Visual C++语言编程开发详解(孙鑫老师)
- 3 weekend110的hadoop中的RPC框架实现机制 + hadoop中的RPC应用实例demo
- vbs获取cpu使用率
- IDEA中SpringBoot项目使用@Data要安装Lombok插件
- write up社工进阶
- Swift之深入解析“泛型”的底层原理
- C# 9 新特性 —— 增强的模式匹配
- fiddler抓包时,出现的 Tunnel to ***** : 443
- git升级后jenkins的报错
- [LevelDB] 编译和使用
- 百度文库的几种下载方法
- 李永乐复习全书线性代数 第三章 向量
- 西门子s300编程实例_几个西门子plc编程实例图解(含程序应用实例)
- git config之后仍无法commit,提示 “fatal: empty ident name“
- 【采集项目-(6)全量数据采集】
- python爬虫之创建表格
- 人行征信2.0对接服务:全业务种类数据,精细您的征信业务管理!
- android 实现区域截图