详解波特率计算公式及含义 比特率和波特率的关系和区别

通常用串口打印乱码大多是因为串口波特率不对 。那么我们应该如何测量实际的波特率呢?在此之前,让我们回顾一下波特率的概念 。
【详解波特率计算公式及含义 比特率和波特率的关系和区别】

详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
什么是波特率和比特率?
比特率的英文是Bitrate,它表示每秒传输的二进制位数 , 单位为比特/秒(bit/s) 。
波特率的英文是Baudrate , 它表示每秒传输的码元符号的个数,是衡量数据传输速率的指标 。
码元是通信信号调制的概念 。具有相同时间间隔的符号通常用于表示通信中的二进制数 。这种的信号称为码元 。
在普通通信传输中,0V代表数字0,5V代表数字1,所以一个码元可以代表0和1两种状态,所以一个码元等于一个二进制位,波特率与比特率一致 。
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
如果0V、2V、4V和6V在通信传输中分别代表二进制数00、01、10和11 , 那么每个码元可以代表四种状态,即两个二进制位 , 因此码元数是二进制位数的一半,此时波特率是比特率的一半 。
因为在许多常见的通信中 , 例如串口通讯中,一个码元代表两种状态 , 所以我们通常直接用波特率来表示比特率 。
串口通讯协议
在串口通信的协议层 , 它规定了数据包的内容,由起始位、主数据、校验位和停止位组成 。通讯双方的数据包格式应一致,才能正常收发数据 。数据帧的组成如下:
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
让我们实际验证数据帧是否真的是这样,编写以下代码:
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
代码非常简单,即使用串口连续向外发送数据0xAA(当然也可以发送其他数据) 。我们的串口配置如下:
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
我们可以用示波器或逻辑分析仪抓取实际信号,看数据是否符合上述格式 。在这里,我们用逻辑分析仪来捕捉usart1的传输信号线(TX):
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
从实际结果中 , 我们可以看出它确实是按照帧格式发送的 。有些人可能对此有所怀疑 。在上面的数据帧的图片中存在空闲状态 。这是什么?空闲、空闲,当然不是在发送数据的状态,我们把代码改为:
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
初始化完成后,只发送一个0XAA,逻辑分析仪捕获的数据是:
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
可见,空闲状态是高电平 。在前面的示例中,我们在while循环中发送了数据0XAA,因此没有空闲状态 。
在这个实验中,我们需要知道两点是:
串口发送的数据首先是低位的 。我们的单片机发送0XAA(10101010B),逻辑分析仪采集的有效数据为01010101b 。
单片机的串口使用TTL电平,这是一个正的逻辑电平信号 。逻辑分析仪采集的数据0对应实际电压0~0.5V,数据1对应实际电压2.4v~5V 。
RS-232电平标准常与TTL电平标准相比较 。例如,
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
TTL电平标准常用于普通电子电路中 。在理想状态下,5V表示二进制逻辑1,0V表示逻辑0 。为了提高串口通信的远距离传输和抗干扰能力 , RS-232电平标准用-15V表示逻辑1,+15V表示逻辑0 。
在旧的台式计算机中,通常有一个RS-232标准的COM端口(也称 DB9 接口):
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
在这个示例程序中,我们将串口波特率设置为115200bps 。在串口通信中,符号只由一个二进制数表示(即只有0 和 1两种状态),因此波特率和比特率是相等的 。
比特率代表每秒传输的二进制位数,所以我们知道传输一比特数据的时间,我们能推导出波特率吗?从逻辑分析仪上我们可以知道,发送一位数据的时间如下:
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
发送一位数据的时间约为8.667us,因此可以计算出一秒钟发送多少位数据:
计算出的波特率为115380bps , 非常接近115200bps 。最后 , 肯定是有一定的错误 。这个错误的原因包括逻辑分析仪的质量和我们的测量环境 。但这个误差也在允许范围内 。您可以看到串口助手接收到的数据是否正确:
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
可以看到接收到的数据是正确的,即波特率是正确的 。
串口波特率对不上怎么解决?
在实践中 。我们可能会遇到这样情况,即代码中配置的波特率与串口助手上设置的波特率相同,但仍然存在一个异常 。
例如,如果我们向串口助手发送一个字符串 , 那么应该显示在串口助手上的字符串就被乱码了 。或者我们发送一个数据到串口助手,发现数据被移动了 。
在这种情况下,大多数波特率都不对应,因此我们必须检查底层文件 。如果代码中波特率计算相关值(时钟)与实际情况不符,就会出现这样的现象 。例如 , 我的一位同事以前遇到过这种情况,这就是原因 。
在使用STM32时,通常使用外部晶体振荡器,如STM32F103系列 。外置晶体振荡器的输入范围为4~16mhz:
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
经验值一般为8MHz,而且一般的demo工程底层代码里默认的也是设置为8MHz , 比如:
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
但是如果实际晶体振荡器没有粘贴8m,就会出现问题(例如串口波特率不正确) 。追溯到源代码 , 串口波特率被分配到USART_Init函数中的,打开这个函数:
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
计算串口波特率需要一个apbclock变量,而这个值得来源从RCC_GetClocksFreq函数来,再打开这个函数:
详解波特率计算公式及含义 比特率和波特率的关系和区别

文章插图
文章插图
所以要注意的是,HSE_VALUE这个值要与实际做对应 。
遇到这种问题找谁说理去 。经验就是不断采坑不断积累的一个过程,早点遇到坑可能也是一件好事 。像类似底层的问题很少遇到,但是一旦遇到那就得比较棘手的问题了 , 需要很有耐心地去查找 。
能用稳定的芯片是一件很幸福的事情 , 用不稳定、不成熟的芯片的时候,那个才是真的难?。?遇到问题真是让人怀疑人生?。砑⒂布⑿酒伎赡苡形侍?。