【STM32】串口通信乱码(认识系统时钟来源)

使用 stm32f407 与电脑主机进行串口通信时,串口助手打印乱码,主要从以下方面进行排查:

  • 检查传输协议设置是否一致(波特率、数据位、停止位、校验位)
  • 检查MCU外部晶振频率是否和库函数设置的一致

最终发现是外部晶振频率和库函数不一致的问题。

一、时钟分析

1、认识时钟源

我们要检查的是 APB2总线的时钟源是否设置正常,因为我们当前使用的串口 USART1 与 APB2 总线(高速总线)相连,从下图看,时钟源有三个:

  • HSI:高速内部时钟,RC振荡器,频率为16MHz
  • HSE:高速外部时钟,接外部时钟源,频率范围为4MHz~26MHz
  • PLL:锁相环倍频输出,其时钟输入源可选择为 HSI/M、HSE/M(本质还是 由HSE或HSI控制)

就结果而言,选择的时钟源是 PLLCLK。(若想了解,可以参考最后一部分)

2、计算系统时钟

现在已经知道了选择的是 PLLCLK 作为时钟源,那么我们就可以顺着这条路线计算系统时钟的值。正点原子 stm32f407 的外设时钟频率 HSE = 8 M

① 输入 HSE

② 经过 M 分频,得到的结果为 HSE / M = 8 / M

③ ④ ⑤ ⑥ 经过 N 倍频,VCO的输出为 (HSE / M ) * N

⑦ 再次 P 分频就得到 SYSCLK = (HSE / M ) * N / P

二、解决外部晶振频率和库函数不一致的问题

从上面可知,选择的系统时钟频率 SYSCLK = (HSE / M ) * N / P,配置文件预期的 SYSCLK = 144MHz,其余参数也都指定了

实际上 HSE 需要视开发板具体情况而定,stm32f4 的 HSE 为 8 MHz,然而配置文件中配置的频率是 25 M,为了不影响原本的SYSCLK,我们需要修改 HSE 和 PLL_M。

  • HSE = 8 M = 8000000
  • PLL_M = (HSE / SYSCLK ) * N / P = 8

1、修改 HSE

HSE 在程序中的体现为宏定义 HSE_VALUE ,该宏定义在 stm32f4xx.h 文件中

这里有两种修改方法,可任选一种修改

2、修改 PLL_M

分频数 M 在程序中的体现是宏定义 PLL_M,该宏定义在 system_stm32f4xx.c 文件中

三、为什么可以确定时钟源为 PLLCLK 而不是 HSE

stm32 在启动的时候就会调用 SystemInit 函数,这个函数就包含了初始化外设的时钟源。这个函数定义在 system_stm32f4xx.c 中。我们直接找到 SetSysClock 函数,这之前的都是将控制寄存器位清零的操作。

我们进入到 SetSysClock 函数,首先是HSE使能,等待时钟准备就绪。刚上电的时候 HSE 晶振不稳定,需要等待 6 个晶振时钟周期。

PLL 使能,等待时钟准备就绪。一开始 PLL 处于被锁定状态,这里需要等待 PLL 解锁。

一切准备就绪,然后将 PLL 设为系统时钟。

参考文章:

在串口通信实验中出现通信乱码怎么办-电子发烧友网 (elecfans.com)

相关推荐
Vizio<3 分钟前
STM32HAL库开发笔记-GPIO输入
笔记·stm32·单片机·嵌入式硬件
硅农深芯23 分钟前
什么时候要用开漏输出(open drain output)?
单片机·嵌入式硬件·gpio·开漏输出·open drain
电子工程师-C512 小时前
基于51单片机的家居环境监测系统
单片机·嵌入式硬件·51单片机
Big_潘大师2 小时前
十轴IMU模块-AHRS角度姿态、加速度计、磁力计、气压陀螺仪传感器
stm32·单片机·嵌入式硬件·arduino·陀螺仪
ghomeway4 小时前
keil使用虚拟的调试串口给调试助手发送数据
单片机·嵌入式硬件
Jason_zhao_MR5 小时前
米尔RK3506核心板SDK重磅升级,解锁三核A7实时控制新架构
linux·嵌入式硬件·物联网·架构·嵌入式·嵌入式实时数据库
小痞同学5 小时前
stm32跑马灯实验
stm32·单片机·嵌入式硬件
宇宙realman_9996 小时前
Flash2833x_API的cmd文件解析
单片机
易水寒陈6 小时前
定时器计数溢出引发的bug
stm32·单片机
染予6 小时前
串口发送之中断方式
单片机·嵌入式硬件