STM32的RCC外设

  • RCC外设,即复位和时钟控制的英文简写。从外设名字来看。RCC外设管理是对STM32芯片的复位和时钟控制进行管理。

那么什么是复位、什么是时钟?

STM32复位功能

  • 系统复位
    • 系统复位将复位除时钟控制寄存器CSR中的复位标志和备份区域中的寄存器以外的所有寄存器为它们的复位数值。
  • 电源复位
    • 电源复位将复位除了备份区域外的所有寄存器
  • 后备域复位
    • 备份区域拥有俩个专门复位,它们只影响备份区域。

系统复位

当以下事件中的一件发生时,产生一个系统复位

  • 1.NRST引脚上拉的低电平(外部复位)
  • 2.窗口看门狗计数终止(WWDG复位)
  • 3.独立看门狗奇数终止(IWDG复位)
  • 4.软件复位(SW复位)
  • 5.低功耗管理复位

    可通过查看RCC_CSR控制状态寄存器中的复位状态标志位识别复位事件来源

以STM32F407VET6最小开发板为例:
image.png

软件复位

通过将Cortex-M3中断应用和复位控制寄存器中的SYSRESETREQ位置’1’将使能该复位,这时,即使执行了进入待机模式的过程,系统将被复位而不是进入待机模式

低功耗管理复位

在以下俩种情况下可产生低功耗管理复位

  • 1.在进入待机模式时产生低功耗管理复位
    • 通过将用户选择字节中的nRST_STDBY位置’1’将使能该府为。这时,即使执行了进入待机模式的过程,系统将被复位而不是进入待机模式。
  • 2.在进入停止模式时产生低功耗管理复位
    • 通过将用户选择字节中的nRST_STDBY位置’1’使能该复位。这时,即使执行了进入停机模式的过程,系统将被复位而不是进入停机模式。

电源复位

当以下事件中之一发生时,产生电源复位

  • 1.上电。掉电复位(POR/PDR复位)
  • 2.从待机模式中返回

备份域复位

备份域拥有俩个专门的复位,它们只影响备份区域
当以下事件中之一发生时,产生备份区域复位

  • 1.软件复位,备份区域复位可由设置备份域控制寄存器(RCC_BDCR)中的BDRST位产生。
  • 2.在VDD和VBAT(电池)俩者掉电的前提下,VDD和VBAT上电将引发备份区域复位

时钟

时钟可以简单理解为”心跳”。对于电子器件来说,时钟就是它的心跳。

STM32芯片,会根据程序给定的时钟节拍来工作。常说的72MHZ、480MHZ就是指STM32的主时钟(系统时钟)频率。STM32芯片就是以这样的频率,在芯片内部做着各种器件的同步工作。

三种不同的时钟源可被用来驱动系统时钟(SYSCLK)

  • HSI振荡器时钟(高速内部时钟)
  • HSE振荡器时钟(高速外部时钟)
  • PLL时钟(锁相环倍频时钟)
  • 40kHz低速内部RC(LSI RC)振荡器(二级时钟源)
  • 32.768kHz低速外部晶体(LSE晶体)(二级时钟源)

这些设备有以下2种二级时钟源:

  • 40KHZ低速内部RC(LSI RC)振荡器,可以用于驱动独立看门狗,或通过程序选择驱动RTC,用于从停机/待机模式下自动唤醒系统
  • 也可以通过程序选择32.769kHz低速外部晶体(LSE晶体)用来驱动RTC(RTCCLK)。当不被使用时任一个时钟源都可被独立地启动或关闭

STM32CubeMx时钟配置

image.png
可配置高速的外部时钟(HSE)和低速时钟(LSE)

  • Disable
  • BYPASS Clock Source
  • Crystal/Ceramic Resonator(晶振)

使用引脚对外输出

  • Master Clock Output 1
  • Master Clock Output 2
  • Master Clock Input(I2S_CKIN)

image.png

  • 一般我们在STm32中使用HSE来作为PLL倍频的时钟源输入,最终通过PLL来对我们输入时钟进行倍频再输出作为系统的主时钟。参考芯片手册的通用工作条件STM32F407VET6的,英文是General operating conditions章节中

image.png
所以我们要将如下时钟源配置好
image.png

  • 分频: 就是做除法。比如8MHz的时钟,分配是/2的话,得到的就是4MHz
  • 对于STM32上的时钟,具体怎么配置,根据需求决定。
  • 时钟频率越高,功耗会更高
  • 另一方面要考虑芯片的工作条件,根据芯片运行工作条件选取时钟频率。

生成HAL库后可以查看以下是否存在时钟配置(main.c中)

  1. void SystemClock_Config(void)
  2. {
  3. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  4. RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  5. /** Configure the main internal regulator output voltage
  6. */
  7. __HAL_RCC_PWR_CLK_ENABLE();
  8. __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  9. /** Initializes the RCC Oscillators according to the specified parameters
  10. * in the RCC_OscInitTypeDef structure.
  11. */
  12. //初始化内部时钟
  13. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  14. RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  15. RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  16. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  17. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  18. {
  19. Error_Handler();
  20. }
  21. /** Initializes the CPU, AHB and APB buses clocks
  22. */
  23. //初始化CPU、AHB、APB总线上的时钟
  24. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  25. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  26. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; //这里选取的系统时钟源是内部时钟源
  27. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;//不同的分屏系数,通过不同的分屏系数,我们可以得到不同的总线时钟
  28. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;//不同的分屏系数,通过不同的分屏系数,我们可以得到不同的总线时钟
  29. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;//不同的分屏系数,通过不同的分屏系数,我们可以得到不同的总线时钟
  30. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  31. {
  32. Error_Handler();
  33. }
  34. }

image.png
对于外部的晶振时钟计算公式

  • 外部时钟/M (分频因子) * N (倍频因子) /P(分频因子)
      1. 25 /25 = 1
      1. 1*336 = 336
      1. 336 / 2 = 168
      1. 168 / 1 = 168
    • HCLK to AHB : 168
    • To Cortex System timer(MHz) : 168 / 1 = 168
    • FCLK Cortex clock(MHz) : 168
    • APB1 peripheral clocks (MHz) (PCLK1) : 168 / 4 = 42
    • APB1 Timer clocks(MHz) : 168 / 2 = 84
    • APB2 peripheral clocks (MHz) (PCLK2) : 168 / 4 = 42
    • APB2 Timer clocks(MHz) : 168 / 2 = 84