良许Linux教程网 干货合集 串口通讯你真的会了吗?不妨看看这些经验

串口通讯你真的会了吗?不妨看看这些经验

平时使用串口打印出现乱码的主要原因大多是由于串口波特率设置不正确。那么,如何测量实际的波特率呢?在这之前,我们先回顾一下波特率的概念。

波特率(Baudrate)和比特率(Bitrate)是两个不同的概念。

比特率表示每秒传输的二进制位数,单位为比特每秒(bit/s)。

而波特率表示每秒传送的码元符号个数,是衡量数据传送速率的指标。

在通信传输中,为了表示二进制数字,常常使用时间间隔相同的符号,这些符号称为码元。比如,0V表示数字0,5V表示数字1,这样一个码元就等于一个二进制比特位,此时波特率的大小与比特率一致。

如果在通信传输中,采用多个电压级别来表示不同的二进制数,比如0V、2V、4V以及6V分别表示二进制数00、01、10、11,那么每个码元就可以表示多种状态,即代表两个二进制比特位。因此,这种情况下的码元数是二进制比特位数的一半,波特率也就是比特率的一半。

由于许多常见的通信(比如串口通信)中,一个码元通常表示两种状态,因此波特率常被直接用来表示比特率。

串口通信协议规定了数据包的内容,包括启始位、主体数据、校验位和停止位。在进行串口通信时,发送方和接收方必须约定好数据包格式,以正常收发数据。数据帧的组成通常如下:

image-20231009211204298
image-20231009211204298

下面我们来实际验证一下其数据帧是不是真的是这样的。编写如下代码:

image-20231009211207070
image-20231009211207070

代码很简单,就是使用串口不断地往外发数据0xAA(当然发送其它数据也是可以的) 。我们的串口配置如下:

image-20231009211209888
image-20231009211209888

我们可以使用示波器或者逻辑分析仪抓取实际信号看看数据是不是符合上面的帧格式。这里,我们使用逻辑分析仪抓取USART1的发送信号线(TX)

image-20231009211212828
image-20231009211212828

从实际结果中我们可以看到的确是按帧格式来发的。这里可能会有人有疑问,上面那个数据帧的图片中有个空闲状态,这个又是什么呢?空闲、空闲,当然是没有在发数据时候的状态呀,我们把我们的代码改为:

image-20231009211215518
image-20231009211215518

在初始化完成之后只发送一次0xAA,逻辑分析仪抓到的数据为:

image-20231009211218681
image-20231009211218681

可见,空闲状态是个高电平。在上一个的范例中,我们一直在while循环中发送数据0xAA,所以就没有空闲状态。

在这个实验中我们需要知道的是两个点是:

  • 串口发送数据是低位先发的。我们单片机发0xAA(10101010B),所以逻辑分析仪抓到的有效数据是01010101B
  • 单片机的串口使用的是TTL电平,为正逻辑电平信号。逻辑分析仪抓到的数据0对应着实际电压0~0.5V,数据1对应着实际电压2.4V-5V

经常与TTL电平标准做对比的是RS-232电平标准,如:

常见的电子电路中常使用 TTL 的电平标准,理想状态下,使用 5V 表示二进制逻辑 1,使用 0V 表示逻辑 0;而为了增加串口通讯的远距离传输及抗干扰能力,RS-232电平标准使用-15V 表示逻辑 1, +15V 表示逻辑 0。

在旧式的台式计算机中一般会有 RS-232 标准的 COM 口(也称 DB9 接口) :

image-20231009211224036
image-20231009211224036

在这个示例程序中,我们设置的串口波特率为115200bps。在串口通讯中,码元只用1个二进制数来表示(即只有0 和 1两种状态),所以波特率与比特率在数值上是相等的。

而比特率表示的是每秒钟传输的二进制位数,那我们知道传一位数据的时间岂不是就可以反推出波特率是多少了吗?从逻辑分析仪中,我们可以知道发送一位数据的时间如下:

image-20231009211228442
image-20231009211228442

发送一位数据的时间大约为8.667us,所以1秒钟发送多少位数据是可以算出来的:

图片
图片

算出来的波特率为115380bps,与115200bps很相近。最终肯定是有一定的误差,这个误差产生的原因包括逻辑分析仪的质量及我们的测量环境等等因素。但是这个误差也是在允许的范围内的,可以看看串口助手接收到的数据是不是正确的:

image-20231009211232077
image-20231009211232077

可见,数据接收正确,也就是波特率对的上了。

串口波特率对不上怎么解决?

在实际中。我们可能会遇到这样的情况,代码里配置的波特率与串口助手上设置的波特率一样了,但还是出现异常情况。

异常情况如我们往串口助手发送字符串,串口助手上本该显示的字符串出现了乱码。或者我们往串口助手发送一个数据,发现数据移位了。

出这种情况大多是波特率对应不上,我们就得自己检查我们的底层文件了,代码中的某个与波特率计算相关的值(时钟)与实际不匹配了,就会出现这样的现象,比如之前我的一位同事就遇到这样的情况就是这个原因导致的。

我们用STM32的时候,一般都是使用外部晶振,比如STM32F103系列,可输入的外部晶振的范围是4~16MHz

image-20231009211235066
image-20231009211235066

经验值往往是8MHz,而且一般的demo工程底层代码里默认的也是设置为8MHz,比如:

image-20231009211237473
image-20231009211237473

但是,如果实际晶振贴的不是8M的话,就出问题了(比如串口波特率就不正确了)。追根溯源,串口波特率是配进USART_Init函数中的,打开这个函数:

image-20231009211239958
image-20231009211239958

计算串口波特率需要一个apbclock变量,而这个值得来源从RCC_GetClocksFreq函数来,再打开这个函数:

image-20231009211242338
image-20231009211242338

所以要注意的是,HSE_VALUE这个值要与实际做对应。

遇到这种问题找谁说理去。。经验就是不断采坑不断积累的一个过程,早点遇到坑可能也是一件好事。像类似底层的问题很少遇到,但是一旦遇到那就得比较棘手的问题了,需要很有耐心地去查找。

能用稳定的芯片是一件很幸福的事情,用不稳定、不成熟的芯片的时候,那个才是真的难啊,遇到问题真是让人怀疑人生啊,软件、硬件、芯片都可能有问题。。。

以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !

137e00002230ad9f26e78-265x300
本文由 良许Linux教程网 发布,可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
良许

作者: 良许

良许,世界500强企业Linux开发工程师,公众号【良许Linux】的作者,全网拥有超30W粉丝。个人标签:创业者,CSDN学院讲师,副业达人,流量玩家,摄影爱好者。
上一篇
下一篇

发表评论

联系我们

联系我们

公众号:良许Linux

在线咨询: QQ交谈

邮箱: yychuyu@163.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部