【基本知识】UART接口
1.简介
(1)UART一种通用异步串口数据总线,最低采用两路信号(TX/RX)即可实现全双工通信,十分简单;
(2)UART采用LSB模式传输,串口数据传输格式如下图所示:
起始位:长度为1位的时间,用于表示发送字符的开始;
数据位:长度长度不固定,一般是8位;
校验位:可以加也可以不加。
停止位:一般是1位、1.5位、2位长度,用于告知接收端字符传输结束;
(3)每个字符的发送都需要有起始位和停止位,对于连续数据也是如此;
2.内部结构
3.实现
发送模块代码如下:
- module uart_tx_path #
- (
- parameter BAUD_DIV = 'd9, //baud
- parameter BAUD_DIV_CAP = 'd4 //baud capture point
- )
- (
- input clk, //main clk
- input rst_n, //reset
- input uart_tx_en, //send one byte data enable
- input[:] uart_tx_byte, //one byte data
- output uart_txd, //the txd pin
- output uart_tx_done //send one byte data done
- );
- //------------------------- Baud rate generator -------------------------
- reg[:] cnt_baud_div;
- reg baud_cap;
- reg baud_start;
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n) begin
- cnt_baud_div <= 'd0;
- end
- else begin
- if(baud_start) begin
- if(cnt_baud_div >= BAUD_DIV) begin
- cnt_baud_div <= 'd0;
- end
- else begin
- cnt_baud_div <= cnt_baud_div + 'b1;
- end
- end
- else begin
- cnt_baud_div <= 'd0;
- end
- end
- end
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n) begin
- baud_cap <= 'b0;
- end
- else begin
- if(cnt_baud_div==BAUD_DIV_CAP) begin
- baud_cap <= 'b1;
- end
- else begin
- baud_cap <= 'b0;
- end
- end
- end
- //-------------------------capture the uart_tx_en posedge-------------------------
- reg uart_tx_en_r0,uart_tx_en_r1;
- wire uart_tx_en_p;
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n) begin
- uart_tx_en_r0 <= 'b0; //uart_tx_en of the idle state is low
- uart_tx_en_r1 <= 'b0;
- end
- else begin
- uart_tx_en_r0 <= uart_tx_en;
- uart_tx_en_r1 <= uart_tx_en_r0;
- end
- end
- assign uart_tx_en_p = (~uart_tx_en_r1 & uart_tx_en_r0)? 'b1:1'b0; //capture the uart_tx_en posedge
- //------------------------- capture the txd data -------------------------
- localparam TX_IDLE = 'b0;
- localparam TX_WORK = 'b1;
- reg state_tx;
- reg uart_tx_done_r;
- reg[:] send_data;
- reg[:] tx_bit;
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n) begin
- state_tx <= TX_IDLE;
- send_data <= 'b1111_1111_11;
- uart_tx_done_r <= 'b0;
- end
- else begin
- case(state_tx)
- TX_IDLE: if(uart_tx_en_p) begin
- baud_start <= 'b1;
- send_data <= {'b1,uart_tx_byte,1'b0};
- state_tx <= TX_WORK;
- uart_tx_done_r <= 'b0;
- end
- else begin
- baud_start <= 'b0;
- send_data <= 'b1111_1111_11;
- state_tx <= TX_IDLE;
- uart_tx_done_r <= 'b0;
- end
- TX_WORK: if(tx_bit == 'd10) begin
- baud_start <= 'b1;
- send_data <= 'b1111_1111_11;
- state_tx <= TX_WORK;
- uart_tx_done_r <= 'b0;
- end
- else if(tx_bit>='d11) begin
- baud_start <= 'b0;
- send_data <= 'b1111_1111_11;
- state_tx <= TX_IDLE;
- uart_tx_done_r <= 'b1;
- end
- else begin
- baud_start <= 'b1;
- send_data <= send_data;
- state_tx <= TX_WORK;
- uart_tx_done_r <= 'b0;
- end
- default: ;
- endcase
- end
- end
- //------------------------- the uart txd work -------------------------
- reg uart_txd_r;
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n) begin
- uart_txd_r <= 'b1; //uart_txd of the idle state is high
- tx_bit <= 'd0;
- end
- else begin
- if(state_tx == TX_WORK) begin
- if(baud_cap) begin
- if (tx_bit <= 'd9)
- uart_txd_r <= send_data[tx_bit];
- else
- uart_txd_r <= 'b1;
- tx_bit <= tx_bit + 'b1;
- end
- else begin
- uart_txd_r <= uart_txd_r;
- tx_bit <= tx_bit;
- end
- end
- else begin
- uart_txd_r <= 'b1;
- tx_bit <= 'd0;
- end
- end
- end
- assign uart_tx_done = uart_tx_done_r;
- assign uart_txd = uart_txd_r;
- endmodule
UART_TX_PATH
接收模块代码如下:
- module uart_rx_path #
- (
- parameter BAUD_DIV = 'd9, //baud
- parameter BAUD_DIV_CAP = 'd4 //baud capture point
- )
- (
- input clk, //main clk
- input rst_n, //reset
- input uart_rxd, //the rxd pin
- output uart_rx_done, //receive one byte data done
- output[:] uart_rx_byte //one byte data
- );
- //------------------------- Baud rate generator -------------------------
- reg[:] cnt_baud_div;
- reg baud_cap;
- reg baud_start;
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n) begin
- cnt_baud_div <= 'd0;
- end
- else begin
- if(baud_start) begin
- if(cnt_baud_div >= BAUD_DIV) begin
- cnt_baud_div <= 'd0;
- end
- else begin
- cnt_baud_div <= cnt_baud_div + 'b1;
- end
- end
- else begin
- cnt_baud_div <= 'd0;
- end
- end
- end
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n) begin
- baud_cap <= 'b0;
- end
- else begin
- if(cnt_baud_div==BAUD_DIV_CAP) begin
- baud_cap <= 'b1;
- end
- else begin
- baud_cap <= 'b0;
- end
- end
- end
- //------------------------- capture the uart start bit -------------------------
- reg uart_rxd_r0,uart_rxd_r1,uart_rxd_r2,uart_rxd_r3;
- wire uart_rxd_n;
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n) begin
- uart_rxd_r0 <= 'b1; //uart_rxd of the idle state is high
- uart_rxd_r1 <= 'b1;
- uart_rxd_r2 <= 'b1;
- uart_rxd_r3 <= 'b1;
- end
- else begin
- uart_rxd_r0 <= uart_rxd;
- uart_rxd_r1 <= uart_rxd_r0;
- uart_rxd_r2 <= uart_rxd_r1;
- uart_rxd_r3 <= uart_rxd_r2;
- end
- end
- assign uart_rxd_n = (uart_rxd_r3 & uart_rxd_r2 & ~uart_rxd_r1 & ~uart_rxd_r0)? 'b1 : 1'b0; //capture the uart_rxd negedge
- //------------------------- the uart rxd work -------------------------
- localparam[:] UART_IDLE = 'd0; //IDLE
- localparam[:] UART_START= 'd1; //START BIT
- localparam[:] UART_BIT0 = 'd2; //BIT0
- localparam[:] UART_BIT1 = 'd3; //BIT1
- localparam[:] UART_BIT2 = 'd4; //BIT2
- localparam[:] UART_BIT3 = 'd5; //BIT3
- localparam[:] UART_BIT4 = 'd6; //BIT4
- localparam[:] UART_BIT5 = 'd7; //BIT5
- localparam[:] UART_BIT6 = 'd8; //BIT6
- localparam[:] UART_BIT7 = 'd9; //BIT7
- localparam[:] UART_STOP = 'd10; //STOP BIT
- reg[:] state_rx;
- reg uart_rx_done_r;
- reg[:] uart_rx_byte_r0;
- reg[:] uart_rx_byte_r1;
- always@(posedge clk or negedge rst_n)
- begin
- if(!rst_n) begin
- state_rx <= UART_IDLE;
- uart_rx_done_r <= 'b0;
- uart_rx_byte_r0 <= 'd0;
- uart_rx_byte_r1 <= 'd0;
- baud_start <= 'b0;
- end
- else begin
- case(state_rx)
- UART_IDLE: if(uart_rxd_n) begin
- uart_rx_done_r <= 'b0;
- baud_start <= 'b1;
- state_rx <= UART_START;
- end
- else begin
- uart_rx_done_r <= 'b0;
- baud_start <= 'b0;
- state_rx <= UART_IDLE;
- end
- UART_START: if(baud_cap) begin
- state_rx <= UART_BIT0;
- end
- else begin
- state_rx <= UART_START;
- end
- UART_BIT0: if(baud_cap) begin
- uart_rx_byte_r0[] <= uart_rxd;
- state_rx <= UART_BIT1;
- end
- else begin
- uart_rx_byte_r0 <= uart_rx_byte_r0;
- state_rx <= UART_BIT0;
- end
- UART_BIT1: if(baud_cap) begin
- uart_rx_byte_r0[] <= uart_rxd;
- state_rx <= UART_BIT2;
- end
- else begin
- uart_rx_byte_r0 <= uart_rx_byte_r0;
- state_rx <= UART_BIT1;
- end
- UART_BIT2: if(baud_cap) begin
- uart_rx_byte_r0[] <= uart_rxd;
- state_rx <= UART_BIT3;
- end
- else begin
- uart_rx_byte_r0 <= uart_rx_byte_r0;
- state_rx <= UART_BIT2;
- end
- UART_BIT3: if(baud_cap) begin
- uart_rx_byte_r0[] <= uart_rxd;
- state_rx <= UART_BIT4;
- end
- else begin
- uart_rx_byte_r0 <= uart_rx_byte_r0;
- state_rx <= UART_BIT3;
- end
- UART_BIT4: if(baud_cap) begin
- uart_rx_byte_r0[] <= uart_rxd;
- state_rx <= UART_BIT5;
- end
- else begin
- uart_rx_byte_r0 <= uart_rx_byte_r0;
- state_rx <= UART_BIT4;
- end
- UART_BIT5: if(baud_cap) begin
- uart_rx_byte_r0[] <= uart_rxd;
- state_rx <= UART_BIT6;
- end
- else begin
- uart_rx_byte_r0 <= uart_rx_byte_r0;
- state_rx <= UART_BIT5;
- end
- UART_BIT6: if(baud_cap) begin
- uart_rx_byte_r0[] <= uart_rxd;
- state_rx <= UART_BIT7;
- end
- else begin
- uart_rx_byte_r0 <= uart_rx_byte_r0;
- state_rx <= UART_BIT6;
- end
- UART_BIT7: if(baud_cap) begin
- uart_rx_byte_r0[] <= uart_rxd;
- state_rx <= UART_STOP;
- end
- else begin
- uart_rx_byte_r0 <= uart_rx_byte_r0;
- state_rx <= UART_BIT7;
- end
- UART_STOP: if(baud_cap) begin
- uart_rx_done_r <= 'b1;
- uart_rx_byte_r1 <= uart_rx_byte_r0;
- baud_start <= 'b0;
- state_rx <= UART_IDLE;
- end
- else begin
- uart_rx_done_r <= 'b0;
- uart_rx_byte_r1 <= uart_rx_byte_r1;
- baud_start <= 'b1;
- state_rx <= UART_STOP;
- end
- default: state_rx <= UART_IDLE;
- endcase
- end
- end
- assign uart_rx_done = uart_rx_done_r;
- assign uart_rx_byte = uart_rx_byte_r1;
- endmodule
UART_RX_PATH
4.参考资料
《通信IC设计》 李庆华著
【基本知识】UART接口的更多相关文章
- UART接口基本知识
Universal asynchronous transciever即同一异步收发器,也就是我们平时所说的串口,是一种最简单,最基本的通信接口. 通信接口按照不同的标准有不同的分类,常见的有同步或异步 ...
- 【原创】FPGA开发手记(一) UART接口
以下内容均以Xilinx的Nexys3作为开发板 1. UART简介 UART(即Universal Asynchronous Receiver Transmitter 通用异步收发器)是广泛使用的串 ...
- UART接口
1.UART UART(Universal Asynchronous Receiver and Transmitter)通用异步收发器(异步串行通信口),是一种通用的数据通信协议,它包括了RS232. ...
- UART接口与COM口的区别
原文地址:https://blog.csdn.net/wordwarwordwar/article/details/78883732 简单的讲:(UART与COM) 嵌入式里面说的串口,一般是指UAR ...
- UART接口介绍
1. 简介 UART, Universal Asynchronous Receiver-Transmitter, 通用异步收发传输器 UART协议规定了通信双方所遵守的规定,属于数据链路层RS232接 ...
- uart接口介绍和认识
接口/总线/驱动 UART (Universal Asynchronous Receiver/Transmitter) 通用异步收发器. UART是用于控制计算机与串行设备的芯片.有一点要注意的是,它 ...
- Cypress的开发板的UART接口打印调试信息
说实话,在官方论坛现在还没有找到相关有用的消息,因为我们这个开发板的UART没引出来. http://www.cypress.com/?app=forum&id=167&rID=527 ...
- MVVM设计模式基础知识--ICommand接口
命令是 Windows Presentation Foundation (WPF) 中的输入机制,它提供的输入处理比设备输入具有更高的语义级别. 命令有若干用途: 第一个用途是将语义以及调用命令的对象 ...
- UART Explained(转载)
做嵌入式开发,UART几乎是必不可少的,调试串口.GPS.GPRS.Bluetooth等模块很多都是用的UART接口.时下火热的IoT也不乏UART的身影,串口的BLE.WIFI.Zigbee.Lor ...
随机推荐
- 使用VS2017遇到的一些小问题
一.去掉预编译头 使用VS2017的时候,发现总是会有"pch.h","stdafx.h"这类预编译头,去掉还会报错.作为新手的我,暂时用不到这些预编译头,于是 ...
- JPA批量插入优化
遇到一个需求是excel数据导入,一次大概会批量插入几万的数据.写完一测奇慢无比. 于是开始打日志,分析代码,发现是插入数据库的时候耗时很长,发现是spring data jpa的原因. 翻看jpa的 ...
- Linux权限:提示-bash: ./startup.sh: Permission denied的解决方案
Linux权限:提示-bash: ./startup.sh: Permission denied的解决方案 Linux上启动Tomcat,结果弹出:-bash: ./startup.sh: Permi ...
- 配置HTTPS全过程
HTTPS配置全过程服务器配置https协议HTTPS,是以安全为目标的HTTP通道,简单讲是HTTP的安全版.即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL. ...
- 运维笔记--Docker文件占用磁盘空间异常处理
场景描述: 1. 服务器运行一段时间后,发现系统盘磁盘空间在不断增加,一开始的时候,不会影响系统,随着时间的推移,磁盘空间在不断增加,直到有一天你会发现系统盘剩余空间即将使用完,值得庆幸的是,如果您使 ...
- Java:JSON和Map相互转换
Java:JSON与Map相互转换 需要jar包:jackson-core-2.6.0.jar,jackson-databind-2.6.0.jar,jackson-annotations-2.6.0 ...
- python-- python threadpool 的前世今生
引出 首先需要了解的是threadpool 的用途,他更适合于用到一些大量的短任务合集,而非一些时间长的任务,换句话说,适合大量的CPU密集型短任务,那些消耗时间较长的IO密集型长任务适合用协程去解决 ...
- 查找算法(5)--Tree table lookup--树表查找
1.树表查找 (1) 最简单的树表查找算法——二叉树查找算法. [1]基本思想:二叉查找树是先对待查找的数据进行生成树,确保树的左分支的值小于右分支的值,然后在就行和每个节点的父节点比较大小,查找最适 ...
- Git采坑与问题排查
目录 Case1:代码库中存大文件 Case1:代码库中存大文件 背景 有这种情况,项目运行需要依赖一个文件(比如需要读一个文件中的数据),那么最直接的方式就是将该文件添加到代码中的分支中,然后将分支 ...
- json 格式化处理工具
json 格式化处理工具 用于JSON的快速命令行处理工具,简单无依赖. 我这边列举一些最常用的: 调试 http 请求时打印格式化后的数据 格式化本地或或流中的数据 获取 json 的键值或进行执行 ...