UART原理

UART原理

       通用异步收发传输器(Universal Asynchronous Receiver / Transmitter),通常称作UART,是一种异步收发传输器,是电脑硬件的一部分。将资料由串行通信与并行通信间作传输转换,作为并行输入成为串行输出的芯片,通常集成于其他通讯接口的连结上。

1、UART发送

       数据的发送实际上就是按照帧格式将寄存器中的并行数据转为串行数据,为其加上起始位和停止位,以一定的波特率进行传输。波特率可以有多种选择,如9600bits/s,14400bits/s,19200bits/s,38400bits/s等
在这里插入图片描述

2、UART接收

       由于传输中有可能会产生毛刺,接收端极有可能将毛刺误认为是起始位,所以要对检测到的下降沿进行判别。一般采用如下的方法:取接收端的时钟频率是发送频率的16倍频,当检测到一个下降沿后,在接下来的16个周期内检测数据线上“0”的个数,若“0”的个数超过8个或者10(根据具体情况设置),则认为是起始位到来,否则认为起始位没有到来,继续检测传输线,等待起始位。
在这里插入图片描述

3、发送主要代码

//============================================================================== 
//开始发送使能
//==============================================================================
reg   start_trig_reg1 ;//延迟一拍触发信号
reg   start_en        ;//开始发送使能信号
always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)start_trig_reg1 <=1'b0;elsestart_trig_reg1 <= i_start_trig ;always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)start_en <= 1'b0 ;else if(!start_trig_reg1&&i_start_trig)//检测触发信号上升沿start_en <= 1'b1 ;elsestart_en <= 1'b0 ;//==============================================================================
//波特率计算
//==============================================================================always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)time_cnt <= 10'h0 ;else if(crt_state==IDLE)time_cnt <= 10'b0 ;else if(time_cnt==10'd867) // 波特率率为115200 ,每一位的周期是8.68us=868个周期time_cnt <= 10'b0 ;elsetime_cnt <=time_cnt + 1'b1  ;//===============================================================================
//并串转换,数据移位
//===============================================================================
always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)shift_data <= 10'h3ff;else if((time_cnt == 9'h0) && (next_state == SEND_START))shift_data  <= {1'b1,i_tx_data[7:0],1'b0}; //time_cnt 每一次为0时,就需要移出一位数据到TX线上else if(time_cnt == 9'h0)shift_data  <= {1'b1,shift_data[9:1]};elseshift_data  <= shift_data;//==============================================================================
//	奇偶校验
//==============================================================================
// 奇偶校验位的产生,parity_cnt 为1 时,数据中1的个数为奇数,该位将在发送校验位时
// 发送出去。计算过程是独立的,属于并行的流水线架构。
always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)parity_cnt <= 1'h0;else if(crt_state == IDLE)parity_cnt  <= 1'h0;else if((time_cnt == 9'd10) && (crt_state == SEND_DATA))parity_cnt  <= parity_cnt + shift_data[0];elseparity_cnt = parity_cnt; //===============================================================================
//检测发送的位顺序,位计数器
//===============================================================================
always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)bit_cnt <= 4'h0;else if(crt_state != next_state)bit_cnt<= 4'h0 ;else if(time_cnt == 10'd867)bit_cnt<= bit_cnt + 4'h1;elsebit_cnt <=bit_cnt;//------------------------------------------------------------------------------
//发送控制状态机
//------------------------------------------------------------------------------
always @ (posedge i_100m_clk or negedge i_rst_n)
beginif(!i_rst_n)crt_state <=  IDLE;elsecrt_state <=  next_state;
endalways @ ( *)case(crt_state)IDLE		:if( start_en )next_state = SEND_START;//进入发送起始位elsenext_state = crt_state;SEND_START	:if((bit_cnt == 4'h0) && (time_cnt == 10'd867))//发送状态必须保持完整的计数周期,每一位的时间严格保证next_state = SEND_DATA  ;elsenext_state = crt_state;   SEND_DATA	:if((bit_cnt == 4'h7) && (time_cnt == 10'd867))//发送8位数据next_state = SEND_PARITY;elsenext_state = crt_state;SEND_PARITY	:if((bit_cnt == 4'h0) && (time_cnt == 10'd867))//奇偶校验位next_state = SEND_STOP;elsenext_state = crt_state;SEND_STOP	:if((bit_cnt == 4'h0) && (time_cnt == 10'd400))//结束位的持续时间不是867个周期next_state = IDLE;elsenext_state = crt_state;default	:	next_state = IDLE;endcase//==========================================================================
//数据发送
//============================================================================
always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)o_uart_tx_bit <= 1'b1;else if(crt_state[1] || crt_state[2]) //发送数据位和起始位o_uart_tx_bit <=  shift_data[0];     else if(crt_state == SEND_PARITY) //发送奇偶校验位o_uart_tx_bit  <= parity_cnt;      else	o_uart_tx_bit <= 1'b1; //==============================================================================
//发送完指示
//==============================================================================always @ (posedge i_100m_clk or negedge i_rst_n)   if(!i_rst_n)   o_tx_done<= 1'b0 ;else if(crt_state [4])                               o_tx_done<= 1'b1 ;  elseo_tx_done<= 1'b0 ;            endmodule

4、接收主要代码

// 计时
//===============================================================          
// 波特率为115200,每一位串行数据持续的周期数=1/115200s=8.68us=868*10ns,因此计数868个周期
reg [9:0] time_cnt ;
reg [3:0] bit_cnt  ;always@(posedge i_100m_clk or negedge i_rst_n)      if(!i_rst_n) time_cnt <= 10'b0 ;else if(crt_state==idle)time_cnt <= 10'b0 ;else if(time_cnt==10'd867) time_cnt <=10'b0 ;elsetime_cnt <=time_cnt+1'b1 ;   always@(posedge i_100m_clk or negedge i_rst_n)//位计数器   if(!i_rst_n) bit_cnt <= 4'b0 ;else if(crt_state==idle)bit_cnt <=4'b0 ;else if(time_cnt==10'd867)bit_cnt <=bit_cnt+1'b1 ;elsebit_cnt <=bit_cnt  ;//================================================================
//状态机
//================================================================                always@(posedge i_100m_clk or negedge i_rst_n)                  if(!i_rst_n)                                              crt_state <= idle  ;elsecrt_state <=next_state ;always@( * )    begincase(crt_state)idle : if( fall_edge )  next_state = start ;elsenext_state = crt_state ;start:  if(bit_cnt==0&&time_cnt==10'd867) //起始位 next_state =data ;elsenext_state = crt_state ;data:  if(bit_cnt==4'd9)  //八位数据位next_state = stop  ;elsenext_state =crt_state ;
//                             parity: if(time_cnt==10'd867)next_state = stop ;elsenext_state = crt_state ;stop :  if(time_cnt==10'd867)next_state = idle  ;elsenext_state =crt_state ;    default: next_state = idle ;endcaseend             //====================================================================//串并转换,移位输出//====================================================================                         
reg [7:0] rx_data_reg1 ;always@(posedge i_100m_clk or negedge i_rst_n)                   if(!i_rst_n)rx_data_reg1 <= 8'b0  ;else if(crt_state[2]&&time_cnt==10'd435) rx_data_reg1 <= {serial_data_r2,rx_data_reg1[7:1]}  ;else  rx_data_reg1 <=rx_data_reg1 ;always@(posedge i_100m_clk or negedge i_rst_n)                  if(!i_rst_n) o_rx_data <=8'b 0 ;else if(bit_cnt==4'd8&&time_cnt==10'd700) o_rx_data <=rx_data_reg1  ;elseo_rx_data <=o_rx_data ;                                             ///=======数据输出指示always@(posedge i_100m_clk or negedge i_rst_n) if(!i_rst_n) o_rx_finish <=1'b0 ;else if(bit_cnt==4'd9&&time_cnt==10'd700) o_rx_finish <=1'b1 ;elseo_rx_finish <=1'b0 ;             endmodule               

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348822.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AttributeError: module 'tensorflow' has no attribute 'placeholder'等一系列tensorflow版本导致的问题

新人tensorflow2.1版本导致程序我无法运行最简单的办法 法1 tensorflow.compat.v1 import tensorflow.compat..v1 as tf tf.disable_v2_behavior() 亲测不好用 法2 卸载2.1&#xff0c;安装老版本 在Terminal界面输入 pip uninstall tensorflow接着输入Y确定卸载。 安装t…

word中一直提示校对错误,如何关闭当前文档校对功能

关闭当前文档校对功能 文件>选项>校对>例外项&#xff0c;选中两个&#xff0c;如图 对比效果&#xff1a;

将测微仪与Spring Boot 2一起使用

这是快速入门&#xff0c;介绍了如何使用出色的Micrometer库来检测基于Spring Boot 2的应用程序并在Prometheus中记录指标 介绍 Micrometer在各种监视工具提供的客户端库上提供了基于Java的外观。 以Prometheus为例&#xff0c;如果我要将Java应用程序与Prometheus集成&#…

与Maven的集成测试

用Maven实施单元测试是很普通的事情&#xff0c;我们大多数人都熟悉项目结构以及单元测试所在的位置。 但是&#xff0c;集成测试是一种不同的情况&#xff0c;大多数情况下它们具有完全不同的要求。 例如&#xff0c;可以让您的单元测试在内存数据库中的h2上运行&#xff0c;…

通信原理-通信系统的组成

第一章 通信系统的组成 1、通信系统一般模型 发送设备&#xff1a;将信源产生的原始电信号变换成适合在信道中传输的形式。变换方式有调制、放大、滤波、编码、多路复用等。 信道&#xff1a;传输信号的通道.即传输媒质。在给子信号通道的同时&#xff0c;信道也会对信号产生损…

使用log4j2免费分配日志记录

介绍 最近&#xff0c;我正在为一个客户端工作&#xff0c;试图为大型精心制作的Java系统消除一些GC暂停。 经过分析后&#xff0c;我意识到大部分垃圾都是通过日志记录产生的&#xff01; 是否有一种简单的方法来删除所有分配&#xff1f; 原来有:) 我应该使用哪个框架进行GC…

Verilog中fork...join 的用法

特点 中间的语句并行执行&#xff1b;&#xff08;延时不累加&#xff09; 不能用于综合&#xff1b; 代码 module signal_gen; reg wave; parameter cycle 5; initial beginforkwave 0;#(cycle) wave 1;#(2*cycle) wave 0;#(3*cycle) wave 1;#(4*cycle…

使用JWT的Cloud Native应用程序

本机云应用程序是为云计算环境开发的应用程序。 对于“ 什么是云原生应用程序 ”这个问题没有具体答案&#xff0c;但是必须满足不同的概念。 在我看来&#xff0c;最重要的功能之一就是能够快速缩放 。 这意味着我们的应用程序在每台服务器上都无法具有任何状态&#xff0c;…

开源项目GoodView点赞效果

点赞1效果&#xff1a; GoodView方法&#xff1a; 使用GoodView的Demo: public class MainActivity extends Activity { Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main)final Good…

开源RefreshListView下拉刷新效果

1、AnimationDrawable java.lang.Object ↳android.graphics.drawable.Drawable ↳android.graphics.drawable.DrawableContainer ↳android.graphics.drawable.AnimationDrawable 文档概述&#xff1a;An object used to create frame-by-frame animations, defined …

View的三大流程之View的测量

1、public class View extends Objectimplements Drawable.Callback KeyEvent.Callback AccessibilityEventSourcejava.lang.Object ↳android.view.View Class Overview This class represents the basic building block for user interface components. A View occupies a …

ListView的使用用ViewHolder提升效率

public class ListView extends AbsListViewjava.lang.Object ↳android.view.View ↳android.view.ViewGroup ↳android.widget.AdapterView<T extends android.widget.Adapter> ↳android.widget.AbsListView ↳android.widget.ListView Class Ove…

电脑还原Mac地址

之前修改过电脑Mac&#xff0c;现在与手机Mac冲突&#xff0c;导致手机无法连接校园网。 控制面板——》打开网络和共享中心——》选择更改适配器设置 本地连接——》右键选择属性 上图选择配置 高级——》在下拉菜单中选择网络地址——》右边选为“不存在” 之后本地连接会自…

聊天ListView使用ViewHolder

聊天界面会展示至少两种布局&#xff0c;即收到消息和发送消息。这样一个ListView与平时使用的ListView的最大不同&#xff0c;在于它有两个不同的布局&#xff1a;收到的布局和发送的布局。需要利用Adapter实现这样的效果。即需要在获取布局的时候判断该获取哪个布局。 public…

动态改变ListView布局

在getView()时&#xff0c;通过判断选择加载不同的布局。 点击某个item的时候&#xff0c;变为foucus状态&#xff0c;其他的items还原。 下面用两个方法给item设置两个不同的布局。 //foucus状态&#xff0c;显示一个ImageViewprivate View addFocusView(int i) {ImageView…

jpa 关系拥有方_JPA:确定关系的归属方

jpa 关系拥有方使用Java Persistence API&#xff08;JPA&#xff09;时&#xff0c;通常需要在两个实体之间创建关系。 这些关系是通过使用外键在数据模型&#xff08;例如数据库&#xff09;中定义的&#xff0c;而在我们的对象模型&#xff08;例如Java&#xff09;中则使用…

获取View坐标

滑动一个View&#xff0c;即移动一个View&#xff0c;改变其当前所处的位置&#xff0c;通过不断改变View的坐标实现滑动的效果。 1、Android坐标系&#xff1a;坐标原点在屏幕左上角。 public void getLocationOnScreen(int[] location) Computes the coordinates of this vi…

李宏毅 课程打包_按功能而不是按层打包课程

李宏毅 课程打包大多数企业Java应用程序在设计上都有一些相似之处。 这些应用程序的打包通常由它们使用的框架&#xff08;如Spring&#xff0c;EJB或Hibernate等&#xff09;驱动。或者&#xff0c;您可以按功能对打包进行分组。 像任何其他有关建模的项目一样&#xff0c;这也…

Java反射,但速度更快

在编译时不知道Java类的最快方法是什么&#xff1f; Java框架通常会这样做。 很多。 它可以直接影响其性能。 因此&#xff0c;让我们对不同的方法进行基准测试&#xff0c;例如反射&#xff0c;方法句柄和代码生成。 用例 假设我们有一个简单的Person类&#xff0c;其中包含名…

Git时间

1、Git是目前世界上最先进的分布式版本控制系统。和集中式版本控制系统相比&#xff0c;分布式版本控制系统的安全性要高很多&#xff0c;因为每个人电脑里都有完整的版本库&#xff0c;某一个人的电脑坏掉了不要紧&#xff0c;随便从其他人那里复制一个就可以了。而集中式版本…