STM32 MCO输出HSE、LSI等时钟波形以及使用LSI发现内部RC震荡频率紊乱的问题

一笑奈何 提交于 2020-01-29 05:37:37

  最近调试产品遇到了一个问题,现象是产品RTC计数不准,定的5s的采样周期,实际表现确是3s多,而且每次间隔还在波动,后来追查到应该是关于STM32的LSI内部RC震荡频率有时会不准,由于问题不好复现,所以采用MCO将内部RC震荡频率输出接到示波器上查看,在此记录下STM32配置MCO(基于HAL库)。

  STM32是通过PA8管脚输出MCO信号的,个别大容量的型号可能有两个IO可输出MCO,我手里使用的STM32L431只有一路,调用库函数配置十分简单,只需要一句话即可:

HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_LSI, RCC_MCODIV_1);

  我们具体看下库函数内的内容:

/**
  * @brief  Select the clock source to output on MCO pin(PA8).
  * @note   PA8 should be configured in alternate function mode.
  * @param  RCC_MCOx  specifies the output direction for the clock source.
  *          For STM32L4xx family this parameter can have only one value:
  *            @arg @ref RCC_MCO1  Clock source to output on MCO1 pin(PA8).
  * @param  RCC_MCOSource  specifies the clock source to output.
  *          This parameter can be one of the following values:
  *            @arg @ref RCC_MCO1SOURCE_NOCLOCK  MCO output disabled, no clock on MCO
  *            @arg @ref RCC_MCO1SOURCE_SYSCLK  system  clock selected as MCO source
  *            @arg @ref RCC_MCO1SOURCE_MSI  MSI clock selected as MCO source
  *            @arg @ref RCC_MCO1SOURCE_HSI  HSI clock selected as MCO source
  *            @arg @ref RCC_MCO1SOURCE_HSE  HSE clock selected as MCO sourcee
  *            @arg @ref RCC_MCO1SOURCE_PLLCLK  main PLL clock selected as MCO source
  *            @arg @ref RCC_MCO1SOURCE_LSI  LSI clock selected as MCO source
  *            @arg @ref RCC_MCO1SOURCE_LSE  LSE clock selected as MCO source
  @if STM32L443xx
  *            @arg @ref RCC_MCO1SOURCE_HSI48  HSI48 clock selected as MCO source for devices with HSI48
  @endif
  * @param  RCC_MCODiv  specifies the MCO prescaler.
  *          This parameter can be one of the following values:
  *            @arg @ref RCC_MCODIV_1  no division applied to MCO clock
  *            @arg @ref RCC_MCODIV_2  division by 2 applied to MCO clock
  *            @arg @ref RCC_MCODIV_4  division by 4 applied to MCO clock
  *            @arg @ref RCC_MCODIV_8  division by 8 applied to MCO clock
  *            @arg @ref RCC_MCODIV_16  division by 16 applied to MCO clock
  * @retval None
  */
void HAL_RCC_MCOConfig( uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  /* Check the parameters */
  assert_param(IS_RCC_MCO(RCC_MCOx));
  assert_param(IS_RCC_MCODIV(RCC_MCODiv));
  assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource));

  /* MCO Clock Enable */
  __MCO1_CLK_ENABLE();

  /* Configue the MCO1 pin in alternate function mode */
  GPIO_InitStruct.Pin = MCO1_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
  HAL_GPIO_Init(MCO1_GPIO_PORT, &GPIO_InitStruct);

  /* Mask MCOSEL[] and MCOPRE[] bits then set MCO1 clock source and prescaler */
  MODIFY_REG(RCC->CFGR, (RCC_CFGR_MCOSEL | RCC_CFGR_MCOPRE), (RCC_MCOSource | RCC_MCODiv ));
}

  由上可看出,STM32L4xx库函数内部已帮我们实现IO的初始化配置,我们无需自己配置,只需要传入三个参数即可,第一个是调用的MCO外设、第二个是需要输出的时钟信号(我这里选择的是LSI),第三个则是所选的时钟分频系数,我这里没有选择分频,所以选分频系数为1即可,值得注意的是若有的库未实现IO的初始化配置,需要由我们自己配置,IO速率一定要选择高速。

  完成上述操作,我们就可以将板子接上示波器查看现象了,这里以内部LSI为例(震荡频率32k左右),波形是这样的:

  前面我说到一个问题,就是内部RC的震荡频率有时会不准,经过测试发现,给设备快速上电断电操作,让设备处在一个有电没电的临界区,很容易会使设备内部的RC震荡频率紊乱,大概频率会在40K~70K之间波动,周期不定,以下实验现象截图:

  该问题应该是设备处在一个上电复位的临界状态,若彻底将设备电放净,该问题不会出现,我们尝试了在VDD和GND之间加了一个电阻,可使设备放电快点,如此尝试问题未复现,由于我们的设备是低功耗设备,加这个电阻会产生多余的功耗,所以实际不能这么解决,后期我会尝试更改选项字节的方式,提高BOR的等级来尝试解决该问题,该问题也有一种其他方式就是采用外置晶振,使用LSE的方式,因为我也测试过外部HSE的情况,也不会出现震荡频率紊乱的现象,若成本要求不高,建议采用外部32K晶振。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!