UART工作原理详解
Posted 17岁boy想当攻城狮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UART工作原理详解相关的知识,希望对你有一定的参考价值。
目录
概述
UART全拼Universal Asynchronous Receiver/Transmitter,即通用异步收发传输器
发展过程
在个人计算机诞生之前就已经存在了串口设备,如电传打字机,工控测量设备,通信调制解调器(现在的路由器),最初的串口就是用一根线直连另外一方,一方发一方收,后来厂商为了完善自己的串口又增加了一根线用于做信号位,主要用于判断流是否可用,同时当时的厂商们的设备不同,芯片的工作频率也不同以及电平信号也不同,导致厂商的设备只能跟自己通讯,没有一个统一的标准非常混乱,后来由无线电制造商协会(Radio Manufacturers' Association:RMA,现:美国电子工业协会(EIA))联合贝尔实验室在1970年代一起制定了一个标准,即历史上第一个通用串口协议标准:RS-232,它规定了波特率(即芯片工作频率),数据线,接受线,流控制线的接法,采用DB25针串口,支持异步。
支持的波特率有:50b/s、75b/s、110b/s、150b/s、300b/s、600b/s、1200b/s、2400b/s、4800b/s、9600b/s、19200b/s
115200这个速率最初是没有的,是后来才加上去的,因为人们发现9600太慢,19200频率又太高,频率越高功耗越高,所以推出一个115200这个合适的频率。
最后随着个人电脑的出现,个人电脑最初的上的接口较小,PCB板子空间也很小,DB25较大,EIA将其中保留的一些针位去除了,形成了后来的DB9针串口,协议依然是RS-232。
由于DB9接口只定义了信号量,但是没有定义与每个引脚的直接关系,导致当时的厂商需要自己去定义每个引脚的作用,这就导致了不同厂商每个引脚的作用不一样,但是功能是一样的,无法相互接在一起,最初有一个比较知名的公司:IBM,它规定了一种定义,后来大多数厂商为了统一都采用IBM的定义。
所以最终IBM成为了PC行业里DB9串口引脚关系的工业标准。
在这一刻UART才叫UART,这里的U即是通用的意思,最初叫ART之类的,因为它没有一个统一的标准,后来IBM统一了之后,才有了U,不同厂商之间的设备可以通过串口进行通讯了。
硬件定义(DP9-RS232)
工作原理(DP9-RS232)
DTR由计算机控制,当为高电平时即告诉目标设备,我已经准备好了,可以给我发送数据了
DSR由目标设备控制,当为高电平时即目标设备告诉计算机,我也可以发送数据了
RTS由计算机控制,告诉目标设备给我发送数据,此时目标设备需要立即给计算机发送数据
CTS由目标设备控制,告诉计算机给目标设备发送数据
DCD是由计算机控制,计算机需要拉高它来告诉目标设备我还在线
在RS232里要求每个字节只能一次传输一个BIT位,所以就需要一个起始位与停止位,为了确保正确性还会有个校验位,这些会在后面说,当将对应的线调整好了之后,需要TXD来确认位的开始与停止
起始位、停止位、校验位(DP9-RS232)
起始位(Start Bit)
发送器是通过发送起始位而开始一个字符传送,起始位使数据线处于逻辑0状态,提示接受器数据传输即将开始,当设定好起始位后,如起始信号为01,那么串口内部时钟开始周期性的采样,如串口内部使用8个时钟周期作为一个采样周期的因子,则每4个周期进行一次采样,如当第4个时钟周期的时候采样为0那么会记到标志寄存器中,当第8个周期采样为1则视为起始信号,这样一个周期就完成了,现在的起始信号一般都不能设置,都采用默认的,即默认的两个低电平,以16个时钟周期为采样因子,每8个时钟周期采一次,若两次之后都为低电平则视为起始信号
起始位为两个低电平00,因为RS232规定要求空闲时电平必须是1,即高电平
数据位(Data Bits)
起始位之后就是传送数据位。数据位一般为8位一个字节的数据(也有6位、7位的情况),低位(LSB)在前,高位(MSB)在后,无法修改高低位的传输优先级
停止位(Stop Bit)
最后一个BIT位,一般为1位,可以设置,一般设置为1或2,最常用的是1,它与数据位相接,当双方通讯协议一致后(停止位数据位都是一样的),当读取完数据位之后在读取一位是高电平的1时则认为收到了停止位,则代表一个数据的结束
校验位(parity Bit)
这是一个比较特殊的位,它使用奇偶的方式校验数据位是否正确,它通常是不用的,因为它属于一个对应的校验控制器来完成,总耗时需要1s,所以如果要添加它的话意味着你每次传输至少要在1s以上,它用来确认数据位上的BIT为1的数量是奇数还是偶数,是一个最简单的状态位,因为传输无法避免干扰等情况,在一些场景恶劣的环境下这个位是非常有用的,当BIT为1的数量为偶数时,校验位为1,为奇数时为0,接收方需要确认这个位与自己实际接收到的是否一致,不一致则可以要求目标方重发,它无法矫正数据,因为它无法确认哪个位有错。
小插曲
现在市面上流行的路由器有一个闭源的算法,就是能够将包的30%损坏修复,类型QR二维码的原理,有兴趣可以研究一下,QR二维码里有一段数据是放矫正信息的,当二维码有一部分无法识别时,会从这个矫正信息里在用特定的算法计算出原始信息,所以我们平时在扫二维码时你可以遮住一小部分,会发现还是可以识别出来,有些工业二维码修复能力更强,因为工业环境很容易出现油漆,污渍等其它遮挡物,遮挡住。
传输过程
如现在要传输“OK”两个字符,O对应的二进制数据为01001111
,K对应的二进制数据为01001011,传输过程如下:
以下过程以RS-232起始信号为标准,数据位为8位,停止位为1位,没有校验位
速率计算
如果想计算一个BIT在当前波特率下每次传输需要耗时多久可以用倒数的方式计算。
如当前的波特率为115200
计算公式:
1/115200=868ns,如果加了奇偶校验位别忘记在加上1s的耗时
即每868ns传输1bit。
波特率
波特率与时钟频率不同,串口允许两个时钟频率不同的设备进行通讯,但要求波特率一致,波特率即你当前的芯片在一定周期内传输BIT的数量,这个波特率就是一定周期,因为两个设备之间的时钟频率不同,一方快,另外一方可能慢,那么就协商一个固定周期,在这个固定周期里只能传输多少BIT位,且这个固定周期里是两个设备的时钟频率都能达到的,如A设备的时钟频率是80hz,B设备的时钟频率是120hz,明显B设备快于A设备,如果不协商明显是无法通讯的,因为不在一个时间线上,则这里进行一次协商,则告诉AB设备我不管你们的时钟频率是快也好,慢也罢,我要求你们在100us里传输8个10个bit位,其中每10US传输一个BIT,那么此时A设备比较慢,但是它的频率也刚好能够达标每10US传递一个BIT,而B设备呢由于比较快,它10us甚至可以传输两个BIT,但是快也没用,因为协商好了规定时间,所以B设备每次到10毫秒时就传输一次,剩下时间则等待时间的到来,这个在芯片内部其实是可以根据设置当前工作时钟频率来完成,如当前波特率要求115200,它每86.8us传输一个bit位,那么只需要将当前工作时钟频率设置为每86.8us为一个周期即可与波特率对应起来。
这样就完成了即便两个设备频率不同也能完成一次正常的通讯,这里需要明确波特率与时钟频率不同,实现波特率的方法不止设置时钟频率一种,也有另外一种方法就是外设时钟,如芯片内部有一个外设时钟,通过设置这个外设时钟的工作频率和中断来完成这个工作,设置外设时钟的好处在于芯片可以做别的事情,等时钟中断来了去发一次数据或接一次数据就可以了。
FIFO
FIFO存储器
在了解UART FIFO功能先说一下FIFO存储器,UART的功能就是基于FIFO存储器
FIFO的概念
随着芯片性能的提升的同时通讯速率也随之提高,因传输率的问题,A设备的传输率要快于B设备的处理能力时就会产生数据流过多的情况,导致B设备的芯片无法及时处理这些数据就会导致部分数据丢失,为了解决这个问题提出了一种存储模式,即FIFO,FIFO全拼是First-In First-Out 即先进先出,就是涉及一个存储器用来临时保存这些数据,然后芯片不再从数据寄存器里去取数据而是在FIFO存储器里去取数据,因为芯片拿到数据后要进行一个处理,这个处理周期可能比较耗时,这就导致外面有新的数据来了没能及时处理,这些数据又被新的数据给覆盖掉了,导致数据的丢失,因为在串口的设计中只有一个数据寄存器,一般是8位寄存器,只能放下一个字节,当又来一个字节串口芯片就会将新的字节填充到数据寄存器里去,它不会等待CPU将数据取走后才填充,因为这样会导致丢失新的数据。
FIFO的出现就是为了解决上述丢包的问题,当数据来了之后串口芯片将数据丢到FIFO的缓冲区里,通过设置最大深度字节来产生一次中断告诉CPU来取走它们,这样就解决了当CPU工作较忙无法取数据时产生丢失的问题,FIFO缓冲区多大取决于你当前芯片的设计,这些可以在你的芯片手册上看到
同时FIFO还提供了一个功能,填充超时,因为有的时候在传输时设备可能会出现不定时的包,如A与B之间传输数据,B设备开启了FIFO功能,并设置填充超出10个字节产生一次中断告知CPU取走数据,但是由于A设备出现了一些问题,暂时不给B设备发数据了,那B设备里的一些数据就永远无法产生中断,那么就有了一个填充超时的中断,即如果特定的时间里没有将FIFO缓冲区填充到设定的指定深度时就会产生这个中断,告诉CPU填充超时了,来处理一下这些没有填满的数据
以下是超时中断的处理流程图
超时设计
这里的超时设计有点特殊,FIFO的超时是指间隔,因为有时候可能是A设备数据发慢了或者其它原因堵塞了导致的,所以FIFO每次收到数据之后会有一个时间间隔,比如我们设置为3,那么当收到一个数据后超过3个周期收到周期没有收到数据,就会产生超时中断,若恰好2个周期数据来了,那么这个周期计数就会被清空置0,这里设置的方式也不是直接设毫秒的,设置是以1分之几为单位,如当前FIFO缓冲区大小是12字节,设置1/8字节为填满字节,1/3为超时间隔,即8个字节产生填满中断,超过3个接收字节时间间隔没有收到数据产生超时中断
有的MCU里的FIFO存储器没有超时中断的功能,用户可以自己写一个,使用自己内部时钟或者写一段时间代码,来定时将RXIFLSEL与TXIFLSEL标志位置1产生中断,这两个位是用于输入与输出中断的。
FIFO缓冲区的清空
FIFO在设计时是不需要用户去清空缓冲区的,我们只需要读就可以了,FIFO是以填充的形式的去覆盖缓冲区的,FIFO自己也不会去清空缓冲区,它只会覆盖缓冲区,通过用户设定的大小将新数据填充到缓冲区里然后产生中断,这样旧数据就被新数据替代也省去一个时间周期来清空缓冲区,那么这就产生一个问题,就是接收时,出现了超时的情况,如我们预设是8个字节为填满,在经过上一次工作后新数据还没有填满8个,只填了4个,那么此时产生超时中断,也就意味着其中4个是新数据剩下4个是旧的没有填充的数据,所以这里需要注意一下
FIFO 输入与输出中断
输入的中断条件是缓冲区里的数据达到用户设置的长度后产生中断告知用户来取走
输出的中断条件是缓冲区里的数据达到用户设置的长度并发出去后产生中断
FIFO缓冲区取数据时的原理
FIFO去取数据时不能指定地址位且只能一次取一个字节,不能取指定地址上的字节,每次产生输入中断取数据时FIFO里有个地址寄存器,当我们每次去取一次以后,这个地址位自动加1,需要用户手动判断是否取完然后清空标志位
其它
一般情况下我们是不会用FIFO的因为UART是低速通讯方式,它每次只传一个BIT在波特率的速率计算下其实速度是很慢的
FIFO在对一些一个字节就要求有响应的一些工作条件下是不建议使用的
UART FIFO
跟上面说的一样,UART这里也只不过将FIFO存储器设计到了UART串口芯片里去了,会提供对应的寄存器让你去配置FIFO存储器,也提供了对应的标志位用于表示当FIFO存储器的当前状态,如TX Ready与RX Ready位用于表示输入与输出缓冲区里是否有数据,当完成一次中断后它俩会被清0,当有新数据覆盖时才会置1,RXIFLSEL与TXIFLSEL标志位用于表示输入与输出缓冲区里的数据长度是否达到用户设置的长度,这两个位会置1并产生中断,这个位不是自动清空的,是需要用户手动去置0,如果不置0会无限进入中断
FIFO缓冲区是有最大字节数的,这个具体要看你的MCU手册里UART这块针对FIFO的设置,UART若支持FIFO功能则会有对应的FIFO寄存器用于控制与开启即nofifo模式与fifo模式
FIFO有两种中断,一种是填满深度中断,一种是超时中断,这两个参数都需要手动设置,第一个中断即需要设置好当前FIFO的深度,如设置为8字节,当FIFO缓冲区填满为8个字节时则响应中断
FIFO针对发送与接收都有对应的缓冲区,当缓冲区达到标准时会将对应的中断标志位置1
USART
USART是支持同步的一种串口模式,它基于UART,全名是:Universal Synchronous/Asynchronous Receiver/Transmitter(通用同步/异步串行接收/发送器)
这里说一下同步、异步,半双工与全双工的意思
异步
异步是一种通讯方式,是指不需要知道何时开始通讯,也不需要知道目标方的时钟频率是多少,只需要一个起始信号,来告诉别人开始通讯了,即异步操作,不需要另外一方一直等着或者每隔一段时间来一次通讯,另外一方只需要在一个周期里进行采样,当采样到了起始信号则开始通讯
半双工
即一个线可以传也可以收,但是不能一边传一边收
全双工
即两根线,一根线穿,一根线收,UART就是异步全双工,可以同时传也可以同时收
同步
同步要求两根线在传输时必须保证数据的一致性,异步是不考虑这个的,异步是可以一边发一边收,它不管发送的与接收的数据是否具有一致性,异步是非阻塞的,而同步是阻塞的,它要求数据发送之后在没有接收到数据之前是不会进行下次通讯的
即同步要求发送与接收都完成之后才开学下一次传输,保证两根线是同步工作。
以上是关于UART工作原理详解的主要内容,如果未能解决你的问题,请参考以下文章