欢迎光临
我们一直在努力

不看代码,从硬件角度理解串口通信

        串口通信为异步双向全双工通信,没有一根专门的时种线,那么从硬件的角度来看,什么叫"异步双向",什么叫"全双工"?

        UART的本质是 时钟控制的移位寄存器通信系统 相信读者在调用所谓"UART_Send"函数之前,必然定义过一个数组用来存储要发送的数据,这是所谓"发送缓冲区"

        问题一:缓冲区,为什么要缓冲?

        缓冲区的存在,是为了解决CPU运行速度极快,而串口通信速度极慢的矛盾。想象一下,若没有发送缓冲区,串口每发1Bit,CPU都要参与其中,那么结果就是CPU效率极低;有了发送缓冲区,CPU就只要负责将字节拆分后塞入发送缓冲寄存器,当发送移位寄存器有空余位置,会有专门的硬件将缓冲寄存器的内容放入移位寄存器。

        同理,接收缓冲寄存器的作用,大家都知道,我们应该在中断中发送和读取串口数据,若没有接收缓冲寄存器,在读取数据中断进行时,万一有中断优先级更高的中断抢占CPU,极易造成数据丢失。

        这张图,分别展示了当你调用"UART_Send"、"UART_Receive"函数的时候,你的硬件经历了什么。              

        问题二:波特率,什么是波特率?

        我们写代码时,常将波特率设置为9600或15200,那这是什么意思?,波特率发生器本质上是一个"可编程分频器",用来控制 发送寄存器什么时候移位,接受采样什么时候采样,对照上图更易理解。其计算公式为

        波特率 = USART输入时钟 / (16 * 分频值)  

        一般是带入比特率和输入时钟计算分频值,如:stm32f103c8t6的输入时钟一般为72 MHZ,常见比特率为115200,代入计算值分频值为39.0625,硬件会自动计算并将这个值写入专门的寄存器(USART_BRR)。在RX读取的时候,会按照 1 bit 的时间读取,计算公式为 1 / 波特率 (秒)结合问题三,你或许会知道串口通信的精妙之处。

        值得注意的是,STM32 的波特率发生器是一个精密的分频器。以 72MHz 主频和 115200 波特率为例,理论分频值为 39.0625。由于寄存器精度限制,硬件会将其量化为最接近的整数值。这微小的舍入误差会导致实际波特率与理论值有细微偏差。只要双方偏差在容错范围(约±2%)内,依靠起始位的重新同步机制,通信依然可靠。但如果晶振不准或计算错误,累积的误差会让采样点‘漂移’出数据位,从而产生乱码。

        问题三:异步,怎么异步的?

        你可能会问:没有时钟线,接收端怎么知道什么时候读取数据?解决办法就是:通过数据本身携带的时序性息。你是否听说过"协议帧","数据包"之类的名词,若我们这样定义:

空闲   起始位   数据位      停止位
 1            0          8bit             1

        若要发送'A',即0x41,UART会发送1 0 10000010 1。不通信时,RX、TX均保持高电平静默。通信的第一步,当RX检测到TX的电平由高转低,就会做好接收的准备;第二步,按照每 bit 时间读取采样(是否能跟问题二结合一下呢)。读取到停止位 1 时,接收结束,双方置高电平静默。再经过接收缓存寄存器,CPU读取,就完成了一次通信,以此循环。UART利用“高电平空闲 + 下降沿起始位”实现可靠的异步同步。

        我们在问题二的波特率计算公式中,将波特率 * 16,那么,为什么是16倍频?是因为串口通信需要极高的采样率。UART 接收端内部以 16 倍于波特率的频率对 RX 引脚进行‘扫描’。当检测到下降沿(起始位)后,它并不立即读取数据,而是等待 8 个时钟周期(正好是 1 bit 时间的一半),确保采样点位于数据波形的最稳定中心,从而最大程度避开信号跳变时的噪声干扰。

        一句话:波特率定快慢,双方要一般;起始位对表,中间采数据,停止位结束

        问题四:全双工,怎么做到的?

        这个问题非常简单,全双工就是双方可以同时接受和发送数据,同时存在两条数据流。

看了这张图,你一定能理解了。

        为什么要共地,通俗讲,就是:所有数字通信本质上都是“电压差”的判断,而电压必须相对于同一个参考点。

        相信通过这篇文章,你对串口通信能有更进一步的理解,文中的不妥之处,也欢迎交流

赞(0)
未经允许不得转载:171主机测评 » 不看代码,从硬件角度理解串口通信
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址