uart串口通信_一文看懂UART串口通信

通用异步收发传输器(Universal Asynchronous Receiver / Transmitter,UART)是一种异步收发传输器。它将要传输的数据在串行通信与并行通信之间加以转换,将发送时将并行数据转换成串行数据来传输,在接收时将串行数据转换成并行数据,UART串口通信属于全双工通信。

01

UART关键参数与时序图

UART通信在使用前需要对其参数进行设置,比如波特率大小、数据位数、奇偶校验类型和停止位,一般奇偶校验不使用。

波特率(Baud):波特率表示每秒钟传送的码元符号的个数。常用的波特率有1200、2400、9600、19200、115200等。在使用时要求通信两端使用相同的波特率进行发送和接收。

数据位数(Data Bits):数据位数表示从传输开始到传输结束发送的数据的位数。默认的是8位,该参数可选择为5、6、7、8。

停止位(Stop Bits):在每个字节(8位)传输完成之后便发送停止位,标志一次数据的传输完成。停止位默认是1位,该参数可选择1、1.5、2。

传输一个完整的字节需要1位起始位、8位数据位、1位停止位,总共需要10位数据,传输10位数据就需要11个波特率时钟脉冲,第一个脉冲标记一次传输的起始位,第11个脉冲标记一次传输的停止位。

UART串口发送一字节的时序图如下所示:

5a974023f4771938dfa206429c6a83db.png

如上图所示为串口传输信息时的时序图,BPS_CLK为波特率时钟信号,当BPS_CLK的第一个上升沿到来时,字节发送Tx开始发送起始位,接下来BPS_CLK的2~9个上升沿发送8位数据位,第10个上升沿到第11个上升沿发送停止位。

基于以上原理,要实现的串口发送模块整体框图其接口定义如下所示:

17fba835010a59a91bca525044ed2f1b.png

clk:50MHz时钟信号;

rst:复位信号;

baud_set:波特率设置信号;

send_en:发送使能信号;

data_byte:8位传输数据位;

tx:信号输出端口;

tx_done:1字节发送结束标志位;

uart_state:发送转态标志位,为1时处于发送转态。

其中波特率作为UART通信中的重要参数之一,对于波特率时钟的生成可以根据计数器的计数值与波特率之间的关系来产生。系统时钟为50MHz的脉冲,其周期System_clk_period为20ns。

f7c8507f4c305d4ee32e4e975a9e5634.png

02

UART_Tx数据的发送

608fb82194a6f8b5539c255d61a778da.png

首先是波特率选择模块的设计,根据上表中这里包含5个波特率来进行设置,如需其他波特率可根据实际使用情况进行修改。

6237675d363eccfef408eac6fc4fe1e8.png

此处为计数器计数生成波特率时钟的程序,当uart_state为1时处于发送状态,这时计数器开始计数,当计数值达到波特率分频计数值bps_DR时便清零再次开始计数,以此循环。时钟脉冲信号bps_clk只在计数值div_cnt为1时为高电平其余时刻均为低电平,这样便生成了波特率时钟bps_clk。

85a6c8d888fd5afbc61367dccae08e60.png

上图为比特率时钟计数器的程序,因为没发送一个字节需要1个起始位、8个数据位和1个停止位,总共需要11个波特率时钟脉冲,此处便为计数11个波特率时钟脉冲。

58275219e9bced914cc1bffc4f39f9bd.png

此处为发送一字节结束标志,当bps_cnt的计数值达到11时,表示一个字节信息发送完毕,这时将标志位拉高。

49c1fbaa6f774285ce232f86dd0f85a8.png

使用输入信号send_en来控制发送状态信号,当输入信号send_en为1时将uart_state置1,这时开始发送数据,当计数值bps_cnt为11时表示一个字节发送完毕,于是便将uart_state置0,一次传输完毕。

e939d51c17fea10b6295e31091a56405.png

此处为了保证发送数据在时钟到来时处于稳定状态,采用数据寄存的形式。如上所示,将发送的数据data_byte寄存到r_data_byte中进行传输。

bps_cnt为波特率脉冲的计数器,每计数11次一字节发送完成一次,bps_cnt为计数值1时发送起始位0,bps_cnt为计数值2~9时发送8位数据位,bps_cnt为10时发送停止位。其余时刻均输出高电平。

仿真程序及仿真波形如下所示:

8ef2f2e1593905e944c3cd8a7c491566.png f0b14aaca55098cd83e4a24dbb115a47.png

其仿真波形如图所示,在仿真程序中首先给data_byte数据位8’b11001010;在仿真波形中,当send_en使能端为1时,数据位data_byte将数据寄存到r_data_byte中,div_cnt开始计数同时开始生成波特率时钟bps_clk,然后bps_cnt开始计数,在bps_cnt计数的同时发送端口rs232_tx也开始发送数据,rs232_tx为低时为发送“0”,为高时发送“1”。另外图中可见当rs232_tx发送完最后一个停止位(高电平)后,标志位tx_done产生了一个尖脉冲,那一瞬间的高电平标记着一个字节的传输完成。

03

UART_Rx数据的接收

UART串口的接收时序图如下所示:

54dbb4924ffacaf9db6c0156f8785b66.png

串口接收时序与发送时序一样,只是采集点一般情况下认为每一组数据的中间区间点为最稳定的状态。因此将每一位数据平均分成16小段,如上图下方Bit_x所示,采集时采集中间部分6、7、8、9、10、11这6个点,对采集的6个点求高低电平发生的概率,取出现次数多的电平作为采样结果。例如采样的6次结果分别为1、1、0、1、1、0,则取电平结果为1;若0出现的次数多则取电平结果为0;若1和0出现的次数相等,则判断当前通信线路受到的干扰较大,本次数据不具有可靠性,本次不进行处理。

根据以上原理,要实现的串口接收模块整体框图其接口定义如下所示:

d9739350e399f135177670cbda653150.png

clk:50MHz时钟信号;

rst:复位信号;

baud_set:波特率设置信号;

rx:信号输入端口;

rx_done:1字节接收结束标志位;

uart_state:接收状态,处于1时为接收状态;

data_byte:接收到的8位数据位。

04

UART_Rx接收程序

bfd0fab826a16ee3ecdabaa02e4ac0af.png

输入数据相对于系统时钟而言也属于异步信号,需要对其进行同步处理。tmp0_rs232_rx和tmp1_rs232_rx为两个数据寄存器,分别寄存上一时刻的信号和当前时刻的信号,nedge为下降沿信号检测,当上一时刻的信号为1(高电平)当前时刻的信号为0(低电平)时,则nedge置1为检测到下降沿,也即检测到起始位信号表示将要接收数据。

f71683f65cbf107e507d730f8d965f30.png

对于接收端的波特率设置,与发送端有一点不同,因为在接收端1位数据位、8位数据位以及1位停止位每一位都要采样16次,即总共需要采样160次,即波特率与计数值的对应关系如下表所示:

1f7a01789da8c000cda3e582a5b71bd7.png

其中System_clk_period为系统时钟周期20ns。

ebeab0c762a470092468e8b71e453011.png

此处的波特率时钟脉冲产生与接收端是一致的,当uart_state为1时处于接收状态,这时计数器开始计数,当计数值达到波特率分频计数值bps_DR时便清零再次开始计数,以此循环。时钟脉冲信号bps_clk只在计数值div_cnt为1时为高电平其余时刻均为低电平,这样便生成了波特率时钟bps_clk。

1327512066d40a17feb611752de31234.png

这里就和发送端不一样了,因为1位起始位、8位数据位和1位停止位,每一位采集16次,故总共要采集160次,所以这里的计数值bps_cnt在采集8'd159(该寄存器为8位,d表示十进制,159为[0-159])次后清零重新开始计数,或者在前12次采集中(起始位采集)起始位大于2了便判断起始位检测出错,对计数值进行清零等待下一次触发。以此循环。

7f1b02238b4ba31c8b47140012ade9c8.png

此处为接收完成标志位,当计数值达到159时表示一次接收结束,便将接收完成标志置1。

e8172ece9fec1ffbd13c65d40d9e9051.png fda781c3b2b643917ec4afc9bdababc5.png

此处为数据接收部分程序,复位时将各部分清零,然后根据计数值bps_cnt使用状态机将接收到的数据依次写入r_data_byte寄存器中,关于r_data_byte的定义,后面的[7:0]表示r_data_byte为8位寄存器,前面的[2:0]表示寄存器r_data_byte中每一位可存储的大小为[0-7]。下面根据bps_cnt的状态机描述的是,对于每一位的中间部分采集6次并累加存储到相应的r_data_byte中。

3bd4971a9d2cd34099891c6f63dda9ca.png

这部分便是对于接收到的数据r_data_byte[n]进行判断,判断其数据的最高位,因为上述已经说明r_data_byte中的每一位r_data_byte[n]都是3位数据[2:0],下面举例说明,当r_data_byte[n]分别为二进制的3'b010、3'b011、3'b100、3'b101时,这几个数据分别对应十进制的2、3、4、5,可以发现当数据累加值小于等于3时,其数据最高位都为0,则可说明数据真实值为0;当数据累加值大于等于4时,其数据最高位都为1,则可说明数据真实值为1。

因此本处的程序:

data_byte[n] <= r_data_byte[n][2];其中n表示第几位数据,后面的[2]表示该为数据的最高位(例如,数据3'd100,该数据为[2:0]共3位,其中最前面的1是第“2”位,中间的0是第“1”位,后面的0是第“0”位),取该为数据的最高位赋值给data_byte[n]。

接下来是看仿真现象,仿真程序与仿真现象如下所示:

d36872ae91a2f90b8943b2f18940f71c.png e336ae6e28f6fb19e4cb7961482f1024.png d7775029bcb7926ffe1903c7deda3410.png

根据仿真波形来看,当系统检测到起始位后,也就是接收端出现下降沿时触发nedge信号使其置1,与此同时uart_state接收状态标志位也置1,接收程序开始,rs232_rx开始接收数据,当rs232_rx数据接收结束之后,检测到停止位时,rx_done接收完成标志位会产生一个高脉冲表示接收完成。

至此,UART的发送端和接收端介绍完毕。

05

Rx与Tx整合

这里我们将Rx接收端接收到的数据通过Rx发送端再发送出去。

22a779e5602693c7e43c0f1423666b76.png 13353964860c0751fbfec1df507fb58e.png

此处我们利用接收完成标志位来触发数据同步,当接收端数据接收完成后,接收完成标志位rx_done将置1,此时将接收到的数据寄存给发送数据位data_byte_tx。当数据寄存完成之后将标志信号tx_en置1过度一个周期,保证内部发送数据位的寄存全部完成,然后再置2触发发送使能信号send_en开始发送数据。

然后仿真程序与仿真图如下所示,看一下效果:

774e591a7f3819c63470bc110ad53eae.png fa29c3b1bb3d968e9956352706838f33.png

从图中可以看出,当接收端接收到起始信号后nedge置1,rs232_rx开始接收数据,当数据接收完成之后,rx_done标志位置1,此时接收到的数据data_byte_rx寄存给发送数据位data_byte_tx,数据同步之后使能发送端send_en,即开始发送数据。

最后将程序下载到FPGA中测试视频如下所示:

  • 13
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值