问题描述

  最近在基于小华半导体MCU HC32F460JETA进行产品开发时(USB虚拟4路串口),发现当虚拟串口配置的波特率为1200bps及以下时,与之对应的物理串口侧并不能收发正确的数据,但是当虚拟串口配置的波特率在2400bps~115200bps这个区间时,物理串口收发数据正常。

排查过程

  分析该问题最简单的方式就是直接在线调试程序。
  如下图,当将设备查到电脑USB口时,此时“设备管理器”中出现了4路串口。
在这里插入图片描述

  通过串口调试助手打开其中一个串口(1200.8.1.E)时,此时代码会执行到如下图的位置(USB_VCP_CtrlParam --> SET_LINE_CODING),用于设置虚拟串口的配置信息(波特率、数据位、校验位、停止位),同时调用与之对于的物理串口。
在这里插入图片描述

  如下图,是华大驱动库串口初始化函数,跟踪程序时发现,调用波特率配置函数USART_SetBaudrate()时返回错误,那就基本定位了问题点了。继续进入USART_SetBaudrate()进行分析。
在这里插入图片描述

  如下图所示,发现DIV_Integer的值过大,超过了宏值USART_BRR_DIV_INTEGER_MAX(0xFF),导致波特率配置失败。由于波特率配置失败,就导致了虚拟串口的波特率与物理串口的波特率不一致,进而导致两者之间通信失败。
在这里插入图片描述
  通过上面的分析,可以清晰的看出波特率配置失败(波特率还是上一次的波特率),校验位、数据位、奇偶校验位等却是配置成功的。那为什么DIV_Integer的值会超限呢,那我们需要从串口的时钟配置去分析。

问题分析

(1)从下图中可以看出USART1、USART2挂在APB1总线上(MAX:100MHz),USART3、USART4挂在APB2总线上(MAX:100MHz)。
在这里插入图片描述

(2)使用外部时钟,晶振频率为12MHz,系统时钟配置为200MHz,PCLK1为2分频,故APB1时钟总线的频率为100MHz。
在这里插入图片描述
(3)下图中,串口配置的预分频值为USART_CLK_DIV16(16分频),那么此时我们可以得到串口1的时钟为APB1_CLK / USART_CLK_DIV16,即(100/16 = 6.25MHz),由此可以确认当前USART1的时钟为6.25MHz。
在这里插入图片描述

(4)下图中,显示的是“波特率寄存器”,该寄存器由两部分组成:整数分频寄存器 DIV_Integer(MAX:0xFF),小数分频寄存器 DIV_Fraction(MAX:0x7F)。

  计算公式:DIV_Integer = C / (B x 8 x (2 - OVER8)) - 1

当波特率(B)为:1200bps,即0.0024MBps,时钟频率(C):6.25MHz,OVER8 = 0时,DIV_Integer = 6.25 / (0.0024 x 8 x (2 - 0)) - 1 = 324 = 0x144;此值已超过寄存器能表示的最大值0xFF,故波特率设置失败。

在这里插入图片描述

解决方案

  从上面的分析可以看出,当波特率过低的时候,需要降低串口的时钟才能得到一个合理的DIV_Integer值。同样的道理,当波特率较高时,必须提高串口的时钟才能得到一个合理的DIV_Integer值。
  因此,在串口初始化之前,首先根据波特率的配置,实时调整串口的预分频值,可以达到合理配置DIV_Integer值的目的。
在这里插入图片描述
在这里插入图片描述

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐