知道单片机运行原理的撸友们都清楚,单片机是基于微控制器(下称MCU)搭建的电子系统。单片机的所有功能其实都是由板载的MCU提供的,Arduino开发板当然也不例外。Arduino(这里单指Uno)的板载MCU为ATmega328P。
在ATmega328P内部,实现串口的部件为USART。
是Universal Synchronous and Asynchronous serial Receiver andTransmitter头字母的缩写,
中文翻译为:通用同步/异步串行收发器。
看到这儿,是不是有点头晕,这到底与串口有什么关系呀?!
串口其实就是一种通讯方式的称呼,背后隐藏的实质是一种数据传输协议。数据一位一位地发送出去和接收进来。
就像做糖葫芦时,一个一个地串进去;吃糖葫芦时,一个一个地撸进嘴里去。名字起得还是很贴合实际的。
串口协议一方面定义了硬件方面的电气连接,另一方面又定义了要实现的协议。而USART就是实现协议的家伙,只是这个家伙是电子硬件系统,而不是草莓视频在线观看APP传统理解的软件了。
而且硬件实现比软件实现的速度和稳定性都要高得多!
这样是不是清晰多了!
USART内部结构是十分复杂的,简而言之主要由三部分组成:波特率发生器、接收单元、发送单元。
每个单元的功能全部由硬件实现,同时以寄存器的形式对用户开放了配置接口(控制寄存器),又以寄存器的形式对用户开放了过程监控(状态寄存器)。
上图为波特率发生单元的内部结构示意图。
波特率发生器为串口的收发单元提供统一的时序,
保证了收发逻辑的准确性和稳定性。
这里要重点说说UBRRn(波特率设置寄存器)。
初始情况下,预分频计数器(Prescaling Down-Counter)自动装载用户写入的UBRRn值,并持续向下计数,计数到0时,重新装置UBRRn值,同时产生一个波特率时钟,由此便实现了波特率的产生。
UBRRn寄存器值与波特率的对应关系见下表所示。
除此之外,其它寄存器主要用于工作模式的配置。
因为正如名称所言,USART有同步和异步两种工作模式:
异步即收发双方各用各的时钟,
波特率产生关键部件见上图红色线框,
基于内部时钟、UBRRn和预分频计数器实现,直接供给本机的收发单元使用。
同步即收发双方共用一个波特率,由同步主机统一提供。主机通过内部时钟产生波特率,一方面供本机的收发单元使用,另一方面通过左下角的XCKn Pin输出给从机使用;从机则从左下角的XCKn Pin接收波特率,供从机内部的收发单元使用。
下图为发送单元结构示意图。
发送前,将待发送数据写入UDRn(数据发送寄存器),这一步是发送过程中用户唯一可参与的环节。
此后,硬件会在检测到移位寄存器(TRANSMIT SHIFT REGISTER)空时,
自动将待发送数据移入,并根据设置好的波特率,通过TXDn引脚将数据发送出去。
注意,虽然在发送过程中,用户是不可能介入的,
但USART设置了状态寄存器以供用户随时读取,以掌握发送的实时进度。
最常用的就是TXC(发送完成)标识和UDRE(发送寄存器空)标识。
TXC会在移位寄存器内数据全部被移出,且发送缓存内也没有数据时被置1,常用于判断数据是否全部发送。UDRE则会在发送数据缓存器为空时置1,以告诉用户可以写入新数据了!
下图为接收单元结构示意图。
工作中,时刻采集来自RxDn的输入信号,
一旦检测到有效的开始位,则在每个波特率周期向接收移位寄存器(RECEIVESHIFT REGISTER)内移入一位数据位,直到接收到第一个停止位。
上面的过程全由硬件自动实现,用户无法参与。直到接收的数据被转移到接收缓存,用户才可以通过UDRn寄存器读取它了。
同样的,虽然在接收过程中,用户是不可能介入的,但USART设置了状态寄存器以供用户随时读取,以掌握接收的实时进度。
最常用的就是RXC(接收完成)标识,只要接收缓存中有未被读取的数据,该位就会被置1,用户也就知道此时可以读数据了。Arduino串口的软件实现
Arduino实现了硬串口和软串口两种形式的串口通信,并且都以类的形式进行管理。
硬串口的操作类为HardwareSerial,定义于HardwareSerial.h源文件中,并对用户公开