问题:
此问题由客户提出,客户在使用 STM32F411 开发产品的时候,采用的是 HIS 作为主时钟,同时使用了UART 与其他 MCU 进行异步通信.
客户发现部分产品 UART 不能正常通信.
调研:
1. 通过使用示波器来测量 UART 的 TX 的波特率,发现误差较大,查看原理图和代码发现他们使用HIS 作为主时钟,且没有使用 PLL 来倍频.
2. 由于 UART 直接用 HIS 作为时钟源,所以考虑通过使用 LSE 校准 STM32F411 的 HIS 值来使得UART 波特率准确.
3. 我们 STM32 官方提供了基于 STM32F0 的 HIS 校准方法 AN4067(基于 STM32Cube).其基本原理如
下写的很清楚:
4. 所以我们将其移植到 STM32F4 上:
a. 替换 STM32F0HAL 为 STM32F4HAL
b. 修改工程器件相关的配置.
c. 去掉与 STM32F4 HIS 校准无关的文件,只保留 his.c/h
d. 修改 main.c 的主程序,初始化校准前频率测试校准后频率测试.
HSIFrequencyBeforeCalib 为校准前的频率值,可以在 IAR 的 Watch 窗口查看.
HSIFrequencyAfterCalib 为校准后的频率值,可以在 IAR 的 Watch 窗口查看.
e. 定义使用 USE_REFERENCE_LSE 和__HSI2LSECALIBRATE_TEST__,使能使用LSE 校准 HIS 功能函数.
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- #ifdef USE_REFERENCE_LSE
- #define HSI_TIMx_COUNTER_PRESCALER ((uint32_t)0)
- /* The signal in input capture is divided by 8 */
- #define HSI_TIMx_IC_DIVIDER TIM_ICPSC_DIV8
- /* The LSE is divided by 8 => LSE/8 = 32768/8 = 4096 */
- #define REFERENCE_FREQUENCY ((uint32_t) 4096) /* The reference frequency
- value in Hz */
- /* Number of measurements in the loop */
- #define HSI_NUMBER_OF_LOOPS ((uint32_t)50)
- /* Connect LSE clock (through MCO) to TIMx Input Capture 1 */
- #ifdef __HSI2LSECALIBRATE_TEST__
- #define HSI_Timer_ConnectInput() do {
- HAL_TIMEx_RemapConfig(&TimHandle, TIM_TIM5_LSE);
- } while(0)
- #else
- #define HSI_Timer_ConnectInput() do {
- HAL_RCC_MCOConfig(RCC_MCO, RCC_MCOSOURCE_LSE, RCC_MCO_DIV1);
- HAL_TIMEx_RemapConfig(&TimHandle, TIM_TIMx_MCO);
- } while(0)
- #endif
复制代码
d.详细代码参考附件源码例程.
结论:
1. STM32 MCU 内部高速时钟是可以通过外部提供的精确时钟源进行校准的.
2. 我们提供一篇应用笔记和参考代码给客户演示如何校准 HIS,基于 STM32Cube 的良好的可移植行,很方便的从 STM32F0 移植到其他 STM32 产品上面.
3. 如果客户在使用异步通信且没有使用 PLL 作为时钟源,建议在系统启动的时候增加校准代码来增强系统的容错能力.
|