[其他ST产品] STM32时钟初始化研究

[复制链接]
 楼主| qn7a12 发表于 2023-1-30 21:11 | 显示全部楼层 |阅读模式
时钟是一个MCU的脉搏,研究清楚脉搏才能更清楚的把握整个MCU的运行。本文主要研究STM32F10x系列,利用官方库文件进行初始化设置。开发环境为MDK4.6,库文件V3.5版本,STM32参考手册。

利用MDK自带仿真器,仿真发现。芯片启动首先打开system_stmf10x.c文件,调用void SystemInit(void)函数。下面贴上代码和中文注释

  1. void SystemInit (void)
  2. {
  3.         /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  4.         /* Set HSION bit */
  5.         RCC->CR |= (uint32_t)0x00000001;        //内部高速时钟使能
  6.        
  7.        
  8.         /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
  9.         //SW:HSI(内部高速8M RC震荡器)作为时钟源
  10.         //AHB(SYSCLK)不分频
  11.         //APB1,APB2不分频
  12.         // PCLK2 2分频后作为ADC时钟
  13.         // HSI时钟2分频后作为PLL输入时钟
  14.         //MCO没有时钟输出
  15.         RCC->CFGR &= (uint32_t)0xF8FF0000;

  16.        
  17.         /* Reset HSEON, CSSON and PLLON bits */
  18.         //HSE振荡器关闭, 时钟安全系统监测器关闭PLL关闭
  19.         RCC->CR &= (uint32_t)0xFEF6FFFF;


  20.         /* Reset HSEBYP bit */
  21.         //清零来旁路外部晶体振荡器。只有在外部4-25MHz振荡器关闭的情况下,才能写入该位。
  22.         RCC->CR &= (uint32_t)0xFFFBFFFF;

  23.        
  24.         /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  25.         //HSI时钟2分频后作为PLL输入时钟
  26.         //HSE不分频器作为PLL输入
  27.         //0000:PLL 2倍频输出
  28.         //0:PLL时钟1.5倍分频作为USB时钟
  29.         RCC->CFGR &= (uint32_t)0xFF80FFFF;

  30.        
  31.         /* Disable all interrupts and clear pending bits  */
  32.         RCC->CIR = 0x009F0000;

  33.        
  34.         /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
  35.         /* Configure the Flash Latency cycles and enable prefetch buffer */
  36.         SetSysClock();

  37.        
  38.         SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
  39. }



评论

———————————————— 版权声明:本文为CSDN博主「notepi」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/wandermen/article/details/46351559  发表于 2023-1-30 22:12
 楼主| qn7a12 发表于 2023-1-30 22:12 | 显示全部楼层
主要是用于重置RCC寄存器,既重置STM32的时钟树。


初始化重置时钟后的时钟树图:
3283663d7d0449c96d.png
 楼主| qn7a12 发表于 2023-1-30 22:14 | 显示全部楼层
上文中还有个函数叫SetSysClock用于设置MCU系统时钟,贴入代码:
  1. static void SetSysClock(void)
  2. {

  3.         #ifdef SYSCLK_FREQ_HSE
  4.           SetSysClockToHSE();
  5.         #elif defined SYSCLK_FREQ_24MHz
  6.           SetSysClockTo24();
  7.         #elif defined SYSCLK_FREQ_36MHz
  8.           SetSysClockTo36();
  9.         #elif defined SYSCLK_FREQ_48MHz
  10.           SetSysClockTo48();
  11.         #elif defined SYSCLK_FREQ_56MHz
  12.           SetSysClockTo56();  
  13.         #elif defined SYSCLK_FREQ_72MHz
  14.           SetSysClockTo72();
  15.         #endif
  16.         /* If none of the define above is enabled, the HSI is used as System clock source (default after reset) */
  17. }

  18. static void SetSysClockTo72(void)
  19. {
  20.         __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

  21.         /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/   


  22.         /* Enable HSE */   
  23.         /*define C_CR_HSEON                        (int32_t)0x00010000)   */
  24.         /*!< External High Speed clock enable */
  25.         //开启HSE振荡器
  26.         RCC->CR |= ((uint32_t)RCC_CR_HSEON);

  27.        
  28.         /* Wait till HSE is ready and if Time out is reached exit */
  29.         //等待HSE起振
  30.         //#define HSEStartUp_TimeOut   HSE_STARTUP_TIMEOUT
  31.         //#define HSE_STARTUP_TIMEOUT   ((uint16_t)0x0500)
  32.         /*!< Time out for HSE start up */
  33.         do
  34.         {
  35.                 HSEStatus = RCC->CR & RCC_CR_HSERDY;
  36.                 StartUpCounter++;  
  37.         } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  38.         if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  39.         {
  40.                 HSEStatus = (uint32_t)0x01;
  41.         }
  42.         else
  43.         {
  44.                 HSEStatus = (uint32_t)0x00;
  45.         }  
  46.        
  47.         if (HSEStatus == (uint32_t)0x01)
  48.         {
  49.                 /* Enable Prefetch Buffer */
  50.                 FLASH->ACR |= FLASH_ACR_PRFTBE;
  51.                
  52.                 /* Flash 2 wait state */
  53.                 FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
  54.                 FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;  

  55.                 /* HCLK = SYSCLK */
  56.                 //#define  RCC_CFGR_HPRE_DIV1      ((uint32_t)0x00000000)        /*!< SYSCLK not divided */
  57.                 //HCLK  :AHB总线时钟,由系统时钟SYSCLK 分频得到,不分频
  58.                 RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;


  59.                 /* PCLK2 = HCLK */
  60.                 // #define  RCC_CFGR_PPRE2_DIV1    ((uint32_t)0x00000000)        /*!< HCLK not divided */
  61.                 //APB2由AHB分频而来,不分频。
  62.                 RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;

  63.                
  64.                 /* PCLK1 = HCLK */
  65.                 //#define  RCC_CFGR_PPRE1_DIV2                 ((uint32_t)0x00000400)        /*!< HCLK divided by 2 */
  66.                 //APB1由AHB分频而来,2分频。
  67.                 RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

  68.                 /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
  69.                 //设置PLLCLK时钟源为HSE,且PLL9倍频
  70.                 RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
  71.                 RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);

  72.                
  73.                 /* Enable PLL */
  74.                 //使能倍频器
  75.                 RCC->CR |= RCC_CR_PLLON;


  76.                 /* Wait till PLL is ready */
  77.                 //等待PLL稳定运行
  78.                 while((RCC->CR & RCC_CR_PLLRDY) == 0)
  79.                 {
  80.                 }
  81.                
  82.                 /* Select PLL as system clock source */
  83.                 //设置PLL作为系统时钟源
  84.                 RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
  85.                 RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;   

  86.                 /* Wait till PLL is used as system clock source */
  87.                 //等待PLL用于系统时钟源
  88.                 while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
  89.                 {
  90.                 }
  91.                 else
  92.                 { /* If HSE fails to start-up, the application will have wrong clock  configuration. User can add here some code to deal with this error */
  93.                 }

  94. }
 楼主| qn7a12 发表于 2023-1-30 22:18 | 显示全部楼层
初始化重置时钟后的时钟树图:
968263d7d0de4a720.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

40

主题

542

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部