|
|
@@ -135,7 +135,457 @@ HSE(8 MHz 外部晶振)
|
|
|
9. 切换 SYSCLK 到 PLL 输出
|
|
|
10. 等待 SYSCLK 切换完成
|
|
|
|
|
|
-### 3.3 SystemCoreClock 变量
|
|
|
+### 3.3 SetSysClockTo72 完整代码(标准库)
|
|
|
+
|
|
|
+以下代码来自 `system_stm32f10x.c`,当定义 `SYSCLK_FREQ_72MHz` 宏时被 `SetSysClock()` 调用:
|
|
|
+
|
|
|
+~~~c
|
|
|
+static void SetSysClockTo72(void)
|
|
|
+{
|
|
|
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
|
|
+
|
|
|
+ /* 使能 HSE */
|
|
|
+ RCC->CR |= ((uint32_t)RCC_CR_HSEON);
|
|
|
+
|
|
|
+ /* 等待 HSE 就绪,超时则退出 */
|
|
|
+ do
|
|
|
+ {
|
|
|
+ HSEStatus = RCC->CR & RCC_CR_HSERDY;
|
|
|
+ StartUpCounter++;
|
|
|
+ } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
|
|
+
|
|
|
+ if ((RCC->CR & RCC_CR_HSERDY) != RESET)
|
|
|
+ HSEStatus = (uint32_t)0x01;
|
|
|
+ else
|
|
|
+ HSEStatus = (uint32_t)0x00;
|
|
|
+
|
|
|
+ if (HSEStatus == (uint32_t)0x01)
|
|
|
+ {
|
|
|
+ /* 使能预取缓冲 */
|
|
|
+ FLASH->ACR |= FLASH_ACR_PRFTBE;
|
|
|
+
|
|
|
+ /* Flash 2 个等待周期(72MHz 需要) */
|
|
|
+ FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
|
|
|
+ FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
|
|
|
+
|
|
|
+ /* HCLK = SYSCLK(AHB 不分频) */
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
|
|
|
+
|
|
|
+ /* PCLK2 = HCLK(APB2 不分频) */
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
|
|
|
+
|
|
|
+ /* PCLK1 = HCLK / 2(APB1 二分频) */
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
|
|
|
+
|
|
|
+ /* PLL 配置:PLLCLK = HSE × 9 = 72 MHz */
|
|
|
+ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC |
|
|
|
+ RCC_CFGR_PLLXTPRE |
|
|
|
+ RCC_CFGR_PLLMULL));
|
|
|
+ RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
|
|
|
+
|
|
|
+ /* 使能 PLL */
|
|
|
+ RCC->CR |= RCC_CR_PLLON;
|
|
|
+ while ((RCC->CR & RCC_CR_PLLRDY) == 0) { }
|
|
|
+
|
|
|
+ /* 选择 PLL 作为系统时钟 */
|
|
|
+ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
|
|
|
+
|
|
|
+ /* 等待 PLL 切换完成 */
|
|
|
+ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) { }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /* HSE 起振失败 — 可在此添加错误处理代码 */
|
|
|
+ }
|
|
|
+}
|
|
|
+~~~
|
|
|
+
|
|
|
+### 3.4 SetSysClockTo72 HAL库等价代码
|
|
|
+
|
|
|
+~~~c
|
|
|
+static void SetSysClockTo72(void)
|
|
|
+{
|
|
|
+ RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
|
|
+ RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
|
|
+
|
|
|
+ /* HSE 振荡器配置:使能 HSE,作为 PLL 输入 */
|
|
|
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
|
|
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
|
|
+ RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
|
|
|
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
|
|
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
|
|
+ RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; /* HSE × 9 = 72 MHz */
|
|
|
+ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { }
|
|
|
+
|
|
|
+ /* 时钟树配置:SYSCLK = PLL72MHz,总线分频 */
|
|
|
+ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK |
|
|
|
+ RCC_CLOCKTYPE_SYSCLK |
|
|
|
+ RCC_CLOCKTYPE_PCLK1 |
|
|
|
+ RCC_CLOCKTYPE_PCLK2;
|
|
|
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
|
|
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; /* HCLK = 72 MHz */
|
|
|
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; /* PCLK2 = 72 MHz */
|
|
|
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; /* PCLK1 = 36 MHz */
|
|
|
+
|
|
|
+ /* Flash 等待周期:72MHz 需要 2 个等待周期 */
|
|
|
+ if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { }
|
|
|
+}
|
|
|
+~~~
|
|
|
+
|
|
|
+### 3.6 SetSysClockToHSE 完整代码(标准库 — HSE 直通)
|
|
|
+
|
|
|
+```c
|
|
|
+static void SetSysClockToHSE(void)
|
|
|
+{
|
|
|
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
|
|
+
|
|
|
+ RCC->CR |= ((uint32_t)RCC_CR_HSEON);
|
|
|
+
|
|
|
+ do
|
|
|
+ {
|
|
|
+ HSEStatus = RCC->CR & RCC_CR_HSERDY;
|
|
|
+ StartUpCounter++;
|
|
|
+ } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
|
|
+
|
|
|
+ if ((RCC->CR & RCC_CR_HSERDY) != RESET)
|
|
|
+ HSEStatus = (uint32_t)0x01;
|
|
|
+ else
|
|
|
+ HSEStatus = (uint32_t)0x00;
|
|
|
+
|
|
|
+ if (HSEStatus == (uint32_t)0x01)
|
|
|
+ {
|
|
|
+ FLASH->ACR |= FLASH_ACR_PRFTBE;
|
|
|
+ FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
|
|
|
+ FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
|
|
|
+
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
|
|
|
+
|
|
|
+ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSE;
|
|
|
+
|
|
|
+ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x04) { }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* --- HAL库等价 --- */
|
|
|
+static void SetSysClockToHSE(void)
|
|
|
+{
|
|
|
+ RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
|
|
+ RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
|
|
+
|
|
|
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
|
|
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
|
|
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
|
|
|
+ HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
|
|
+
|
|
|
+ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK |
|
|
|
+ RCC_CLOCKTYPE_SYSCLK |
|
|
|
+ RCC_CLOCKTYPE_PCLK1 |
|
|
|
+ RCC_CLOCKTYPE_PCLK2;
|
|
|
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
|
|
|
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
|
|
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
|
|
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
|
|
|
+ HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 3.7 SetSysClockTo24 完整代码(标准库 — 24 MHz)
|
|
|
+
|
|
|
+```c
|
|
|
+static void SetSysClockTo24(void)
|
|
|
+{
|
|
|
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
|
|
+
|
|
|
+ RCC->CR |= ((uint32_t)RCC_CR_HSEON);
|
|
|
+
|
|
|
+ do
|
|
|
+ {
|
|
|
+ HSEStatus = RCC->CR & RCC_CR_HSERDY;
|
|
|
+ StartUpCounter++;
|
|
|
+ } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
|
|
+
|
|
|
+ if ((RCC->CR & RCC_CR_HSERDY) != RESET)
|
|
|
+ HSEStatus = (uint32_t)0x01;
|
|
|
+ else
|
|
|
+ HSEStatus = (uint32_t)0x00;
|
|
|
+
|
|
|
+ if (HSEStatus == (uint32_t)0x01)
|
|
|
+ {
|
|
|
+ FLASH->ACR |= FLASH_ACR_PRFTBE;
|
|
|
+ FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
|
|
|
+ FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
|
|
|
+
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
|
|
|
+
|
|
|
+ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
|
|
|
+ RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL6);
|
|
|
+
|
|
|
+ RCC->CR |= RCC_CR_PLLON;
|
|
|
+ while ((RCC->CR & RCC_CR_PLLRDY) == 0) { }
|
|
|
+
|
|
|
+ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
|
|
|
+ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) { }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* --- HAL库等价 --- */
|
|
|
+static void SetSysClockTo24(void)
|
|
|
+{
|
|
|
+ RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
|
|
+ RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
|
|
+
|
|
|
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
|
|
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
|
|
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
|
|
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
|
|
+ RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
|
|
|
+ HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
|
|
+
|
|
|
+ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_ALL;
|
|
|
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
|
|
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
|
|
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
|
|
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
|
|
|
+ HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 3.8 SetSysClockTo36 完整代码(标准库 — 36 MHz)
|
|
|
+
|
|
|
+```c
|
|
|
+static void SetSysClockTo36(void)
|
|
|
+{
|
|
|
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
|
|
+
|
|
|
+ RCC->CR |= ((uint32_t)RCC_CR_HSEON);
|
|
|
+
|
|
|
+ do
|
|
|
+ {
|
|
|
+ HSEStatus = RCC->CR & RCC_CR_HSERDY;
|
|
|
+ StartUpCounter++;
|
|
|
+ } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
|
|
+
|
|
|
+ if ((RCC->CR & RCC_CR_HSERDY) != RESET)
|
|
|
+ HSEStatus = (uint32_t)0x01;
|
|
|
+ else
|
|
|
+ HSEStatus = (uint32_t)0x00;
|
|
|
+
|
|
|
+ if (HSEStatus == (uint32_t)0x01)
|
|
|
+ {
|
|
|
+ FLASH->ACR |= FLASH_ACR_PRFTBE;
|
|
|
+ FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
|
|
|
+ FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;
|
|
|
+
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
|
|
|
+
|
|
|
+ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
|
|
|
+ RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL9);
|
|
|
+
|
|
|
+ RCC->CR |= RCC_CR_PLLON;
|
|
|
+ while ((RCC->CR & RCC_CR_PLLRDY) == 0) { }
|
|
|
+
|
|
|
+ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
|
|
|
+ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) { }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* HAL库等价版 */
|
|
|
+static void SetSysClockTo36(void)
|
|
|
+{
|
|
|
+ RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
|
|
+ RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
|
|
+
|
|
|
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
|
|
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
|
|
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
|
|
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
|
|
+ RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
|
|
|
+ HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
|
|
+
|
|
|
+ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_ALL;
|
|
|
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
|
|
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
|
|
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
|
|
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
|
|
|
+ HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 3.9 SetSysClockTo48 完整代码(标准库 — 48 MHz)
|
|
|
+
|
|
|
+```c
|
|
|
+static void SetSysClockTo48(void)
|
|
|
+{
|
|
|
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
|
|
+
|
|
|
+ RCC->CR |= ((uint32_t)RCC_CR_HSEON);
|
|
|
+
|
|
|
+ do
|
|
|
+ {
|
|
|
+ HSEStatus = RCC->CR & RCC_CR_HSERDY;
|
|
|
+ StartUpCounter++;
|
|
|
+ } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
|
|
+
|
|
|
+ if ((RCC->CR & RCC_CR_HSERDY) != RESET)
|
|
|
+ HSEStatus = (uint32_t)0x01;
|
|
|
+ else
|
|
|
+ HSEStatus = (uint32_t)0x00;
|
|
|
+
|
|
|
+ if (HSEStatus == (uint32_t)0x01)
|
|
|
+ {
|
|
|
+ FLASH->ACR |= FLASH_ACR_PRFTBE;
|
|
|
+ FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
|
|
|
+ FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;
|
|
|
+
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
|
|
|
+
|
|
|
+ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
|
|
|
+ RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6);
|
|
|
+
|
|
|
+ RCC->CR |= RCC_CR_PLLON;
|
|
|
+ while ((RCC->CR & RCC_CR_PLLRDY) == 0) { }
|
|
|
+
|
|
|
+ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
|
|
|
+ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) { }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* HAL库等价版 */
|
|
|
+static void SetSysClockTo48(void)
|
|
|
+{
|
|
|
+ RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
|
|
+ RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
|
|
+
|
|
|
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
|
|
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
|
|
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
|
|
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
|
|
+ RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6;
|
|
|
+ HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
|
|
+
|
|
|
+ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_ALL;
|
|
|
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
|
|
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
|
|
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
|
|
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
|
|
|
+ HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 3.10 SetSysClockTo56 完整代码(标准库 — 56 MHz)
|
|
|
+
|
|
|
+```c
|
|
|
+static void SetSysClockTo56(void)
|
|
|
+{
|
|
|
+ __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
|
|
|
+
|
|
|
+ RCC->CR |= ((uint32_t)RCC_CR_HSEON);
|
|
|
+
|
|
|
+ do
|
|
|
+ {
|
|
|
+ HSEStatus = RCC->CR & RCC_CR_HSERDY;
|
|
|
+ StartUpCounter++;
|
|
|
+ } while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
|
|
|
+
|
|
|
+ if ((RCC->CR & RCC_CR_HSERDY) != RESET)
|
|
|
+ HSEStatus = (uint32_t)0x01;
|
|
|
+ else
|
|
|
+ HSEStatus = (uint32_t)0x00;
|
|
|
+
|
|
|
+ if (HSEStatus == (uint32_t)0x01)
|
|
|
+ {
|
|
|
+ FLASH->ACR |= FLASH_ACR_PRFTBE;
|
|
|
+ FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
|
|
|
+ FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
|
|
|
+
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
|
|
|
+
|
|
|
+ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
|
|
|
+ RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL7);
|
|
|
+
|
|
|
+ RCC->CR |= RCC_CR_PLLON;
|
|
|
+ while ((RCC->CR & RCC_CR_PLLRDY) == 0) { }
|
|
|
+
|
|
|
+ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
|
|
|
+ RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
|
|
|
+ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08) { }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* HAL库等价版 */
|
|
|
+static void SetSysClockTo56(void)
|
|
|
+{
|
|
|
+ RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
|
|
+ RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
|
|
+
|
|
|
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
|
|
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
|
|
+ RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
|
|
+ RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
|
|
+ RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL7;
|
|
|
+ HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
|
|
+
|
|
|
+ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_ALL;
|
|
|
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
|
|
+ RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
|
|
+ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
|
|
+ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
|
|
|
+ HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 3.11 MCO 时钟输出配置
|
|
|
+
|
|
|
+MCO(Microcontroller Clock Output)可将内部时钟从 PA8 引脚输出,供外部测量或作为其它芯片的时钟源。
|
|
|
+
|
|
|
+~~~c
|
|
|
+/* 标准库版:PA8 输出 PLL/2 = 36 MHz */
|
|
|
+GPIO_InitTypeDef GPIO_InitStructure;
|
|
|
+RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
|
|
+
|
|
|
+GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
|
|
|
+GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
+GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+GPIO_Init(GPIOA, &GPIO_InitStructure);
|
|
|
+
|
|
|
+RCC_MCOConfig(RCC_MCO_PLLCLK_DIV2); /* MCO = PLL / 2 */
|
|
|
+
|
|
|
+/* 其他可选时钟源 */
|
|
|
+// RCC_MCOConfig(RCC_MCO_HSI); /* MCO = HSI 8 MHz */
|
|
|
+// RCC_MCOConfig(RCC_MCO_HSE); /* MCO = HSE 8 MHz */
|
|
|
+// RCC_MCOConfig(RCC_MCO_SYSCLK); /* MCO = SYSCLK */
|
|
|
+// RCC_MCOConfig(RCC_MCO_PLLCLK_DIV2);/* MCO = PLLCLK / 2 */
|
|
|
+~~~
|
|
|
+
|
|
|
+~~~c
|
|
|
+/* HAL库等价:PA8 输出 PLL/2 = 36 MHz */
|
|
|
+GPIO_InitTypeDef GPIO_InitStruct = {0};
|
|
|
+
|
|
|
+__HAL_RCC_GPIOA_CLK_ENABLE();
|
|
|
+GPIO_InitStruct.Pin = GPIO_PIN_8;
|
|
|
+GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
|
|
+GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
|
|
+HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
|
|
+
|
|
|
+HAL_RCC_MCOConfig(RCC_MCO1SOURCE_PLLCLK, RCC_MCODIV_2);
|
|
|
+~~~
|
|
|
+
|
|
|
+### 3.12 SystemCoreClock 变量
|
|
|
|
|
|
```c
|
|
|
// system_stm32f10x.c 中定义
|
|
|
@@ -153,11 +603,29 @@ OLED_ShowNum(1, 8, SystemCoreClock, 8); // 显示当前系统主频
|
|
|
|
|
|
RCC 通过三个寄存器组控制外设时钟的开关。使用时只需调用以下标准库函数:
|
|
|
|
|
|
-| 总线 | 函数 | 示例 |
|
|
|
-|------|------|------|
|
|
|
-| APB2 | `RCC_APB2PeriphClockCmd()` | `RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE)` |
|
|
|
-| APB1 | `RCC_APB1PeriphClockCmd()` | `RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE)` |
|
|
|
-| AHB | `RCC_AHBPeriphClockCmd()` | `RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE)` |
|
|
|
+| 总线 | 标准库函数 | HAL 宏 |
|
|
|
+|------|-----------|--------|
|
|
|
+| APB2 | `RCC_APB2PeriphClockCmd()` | `__HAL_RCC_GPIOA_CLK_ENABLE()` 等 |
|
|
|
+| APB1 | `RCC_APB1PeriphClockCmd()` | `__HAL_RCC_TIM2_CLK_ENABLE()` 等 |
|
|
|
+| AHB | `RCC_AHBPeriphClockCmd()` | `__HAL_RCC_DMA1_CLK_ENABLE()` 等 |
|
|
|
+
|
|
|
+**标准库示例:**
|
|
|
+```c
|
|
|
+RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
|
|
|
+RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
|
|
+RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
|
|
|
+```
|
|
|
+
|
|
|
+**HAL库示例:**
|
|
|
+```c
|
|
|
+__HAL_RCC_GPIOB_CLK_ENABLE(); /* APB2 — GPIOB 时钟使能 */
|
|
|
+__HAL_RCC_TIM2_CLK_ENABLE(); /* APB1 — TIM2 时钟使能 */
|
|
|
+__HAL_RCC_DMA1_CLK_ENABLE(); /* AHB — DMA1 时钟使能 */
|
|
|
+
|
|
|
+__HAL_RCC_USART1_CLK_ENABLE(); /* APB2 — USART1 时钟使能 */
|
|
|
+__HAL_RCC_ADC1_CLK_ENABLE(); /* APB2 — ADC1 时钟使能 */
|
|
|
+__HAL_RCC_SPI1_CLK_ENABLE(); /* APB2 — SPI1 时钟使能 */
|
|
|
+```
|
|
|
|
|
|
**不能在初始化函数中关闭时钟后再开启**,否则外设寄存器会丢失配置。
|
|
|
|