你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32心得:SYSTEMInit初始化函数解读

[复制链接]
STMCU小助手 发布时间:2022-11-20 15:40
之前初学STM32开发板的时候,也写了几篇关于时钟系统配置的文章文章一和文章二,最近又仔细回顾了官方给的SystemInit ()函数,对其做了更好的解读。所谓读书百遍其义自见。

主要的函数:void SystemInit (void)
包含的函数:static void SetSysClock(void);static void SetSysClockTo72(void)

  1. /**
  2. ********************************  STM32F10x  *******************************************************
  3. * @文件名称: systeminit.c解读版
  4. * @作者名称: 闲人Ne
  5. * @库版本号: V3.5.0
  6. * @工程版本: V1.0.0
  7. * @开发日期: 2020年12月15日
  8. * @摘要简述: 本文件源于system_stm32f10x.c文件里的部分函数,不做任何修改,单独拿出来只为对其做详细解读。
  9. ****************************************************************************************************/
  10. /************************************************************************************************
  11. 函数名称:SystemInit ()
  12. 函数功能:系统初始化函数
  13. 入口参数:无
  14. 返回参数:无
  15. 开发作者:闲人Ne
  16. 参考资料:1)RCC寄存器名称:RCC_CR (时钟控制寄存器) RCC_CFGR(时钟配置寄存器)RCC_CIR(时钟中断寄存器)
  17. *************************************************************************************************/
  18. void SystemInit (void)
  19. {
  20.   // 针对RCC_CR,HSION[0]内部高速时钟使能,设1,即内部8MHz振荡器开启
  21.   RCC->CR |= (uint32_t)0x00000001;   
  22.   #ifndef STM32F10X_CL
  23.   /* 针对RCC_CFGR,SW    [0:1]   系统时钟切换,        设00,   即HSI作为系统时钟;
  24.                   SWS   [2:3]   系统时钟切换状态,    设00,   即HSI作为系统时钟;
  25.                   HPRE  [4:7]   AHP预分频,          设0000, 即SYSCLK不分频;
  26.                   PPRE1 [8:10]  低速APB预分频(APB1), 设000,  即HCLK不分频,从而决定PCLK1时钟;
  27.                             PPRE2  [11:13] 高速APB预分频(APB2),设000,  即HCLK不分频,从而决定PCLK2时钟;
  28.                  ADCPRE [14:15] ADC预分频,          设00,   即PCLK2 2分频后作为ADC时钟;
  29.                  MOC    [24:26] 微控制器时钟输出,    设000,  即没有时钟输出 */  
  30.    RCC->CFGR &= (uint32_t)0xF8FF0000;  
  31.   #else
  32.    RCC->CFGR &= (uint32_t)0xF0FF0000;  // 不执行,因为我用的是STM32F10X_HD
  33.   #endif
  34.   /* 针对RCC_CR,   HSEON    [16] 外部高速时钟使能,    设0,   即外部HSE振荡器关闭;
  35.                   CSSON    [19] 时钟安全系统使能,     设0,   即时钟监测器关闭;
  36.                   PCCON    [24] PLL使能,             设0,   PCC关闭 */
  37.   RCC->CR &= (uint32_t)0xFEF6FFFF;
  38.   // 针对RCC_CR,   HSEBYP   [18] 外部高速时钟旁路,    设0,   即外部4-16MHz振荡器没有旁路
  39.   RCC->CR &= (uint32_t)0xFFFBFFFF;
  40.   /* 针对RCC_CFGR, PCCSRC   [16] PLL输入时钟源,       设0,   即HSI振荡器时钟经2分频后作为PLL输入时钟;
  41.                   PLLXTPRE [17] HSE分频器作为PLL输入,设0,    即HSE不分频;
  42.                   PLLMUL   [18: 21]PLL倍频系数,      设0000,即PLL 2倍频输出;
  43.                   USBPRE   [22] USB预分频,           设0,   即PLL时钟1.5倍分频作为USB时钟 */
  44.   RCC->CFGR &= (uint32_t)0xFF80FFFF;
  45.   #ifdef STM32F10X_CL  // 不执行,因为用的是STM32F10X_HD
  46.    RCC->CR &= (uint32_t)0xEBFFFFFF;
  47.    RCC->CIR = 0x00FF0000;
  48.    RCC->CFGR2 = 0x00000000;
  49.   #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) // 不执行,因为用的是STM32F10X_HD
  50.    RCC->CIR = 0x009F0000;
  51.    RCC->CFGR2 = 0x00000000;      
  52.   #else // 执行,因为用的是STM32F10X_HD
  53.   /* 针对RCC_CIR, LSIRDYF [0]  LSI就绪中断标志,      设0, 即无内部40kHz RC振荡器产生的时钟就绪中断;
  54.                  LSERDYF [1]  LSE就绪中断标志,      设0, 即无外部32kHz振荡器产生的时钟就绪中断;
  55.                  HSIRDYF [2]  HSI就绪中断标志,      设0, 即无内部8MHz RC振荡器产生的时钟就绪中断;
  56.                  HSERDYF [3]  HSE就绪中断标志,      设0, 即无外部4-16MHz振荡器产生的时钟就绪中断;
  57.                  PLLRDYF [4]  PLL就绪中断标志,      设0, 即无PLL上锁产生的时钟就绪中断;
  58.                  CSSF    [7]  时钟安全系统中断标志, 设0, 即无HSE时钟失效产生的安全系统中断;
  59.                  LSIRDYIE[8]  LSI就绪中断使能,      设0, 即LSI就绪中断关闭;
  60.                  LSERDYIE[9]  LSE就绪中断使能,      设0, 即LSE就绪中断关闭;
  61.                  HSIRDYIE[10] HSI就绪中断使能,      设0, 即HSI就绪中断关闭;
  62.                  HSERDYIE[11] HSE就绪中断使能,      设0, 即HSE就绪中断关闭;
  63.                  PLLRDYIE[12] PLL就绪中断使能,      设0, 即PLL就绪中断关闭;
  64.                  LSIRDYC [16] 清除LSI就绪中断,      设1, 即清除LSI就绪中断标志位LSIRDYF;
  65.                  LSERDYC [17] 清除LSE就绪中断,      设1, 清除LSE就绪中断标志位LSERDYF;
  66.                  HSIRDYC [18] 清除HSI就绪中断,      设1, 清除HSI就绪中断标志位HSIRDYF;
  67.                            HSERDYC [19] 清除HSE就绪中断,      设1, 清除HSE就绪中断标志位HSERDYF;
  68.                            PLLRDYC [20] 清除PLL就绪中断,      设1, 清除PLL就绪中断标志位PLLRDYF */
  69.    RCC->CIR = 0x009F0000;  
  70.   #endif
  71.   #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)   
  72.    #ifdef DATA_IN_ExtSRAM
  73.     SystemInit_ExtMemCtl();                // 不执行
  74.    #endif
  75.   #endif
  76.   /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
  77.   /* Configure the Flash Latency cycles and enable prefetch buffer */
  78.   SetSysClock();  // 设置系统时钟函数,往下翻会有解读   
  79.   #ifdef VECT_TAB_SRAM
  80.    SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; // 不执行
  81.   #else
  82.    SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
  83.   #endif
  84. }

  85. /************************************************
  86. 函数名称:SetSysClock()
  87. 函数功能:设置系统时钟函数
  88. 入口参数:无
  89. 返回参数:无
  90. 开发作者:闲人Ne
  91. *************************************************/
  92. static void SetSysClock(void)
  93. {
  94. #ifdef SYSCLK_FREQ_HSE
  95.   SetSysClockToHSE();   // 不执行
  96. #elif defined SYSCLK_FREQ_24MHz
  97.   SetSysClockTo24();    // 不执行
  98. #elif defined SYSCLK_FREQ_36MHz
  99.   SetSysClockTo36();    // 不执行
  100. #elif defined SYSCLK_FREQ_48MHz
  101.   SetSysClockTo48();    // 不执行
  102. #elif defined SYSCLK_FREQ_56MHz
  103.   SetSysClockTo56();    // 不执行
  104. #elif defined SYSCLK_FREQ_72MHz
  105.   SetSysClockTo72();    // 执行,因为只定义了SYSCLK_FREQ_72MHz=72000000,往下翻会有解读
  106. #endif
  107. }

  108. /************************************************
  109. 函数名称:SetSysClock()
  110. 函数功能:设置系统时钟函数
  111. 入口参数:无
  112. 返回参数:无
  113. 开发作者:闲人Ne
  114. *************************************************/
  115. static void SetSysClockTo72(void)
  116. {
  117.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  118.   /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/   
  119.   // RCC_CR_HSEON=0x00010000,针对RCC_CR,HSEON[16]外部高速时钟使能,设1,即外部HSE振荡器开启  
  120.   RCC->CR |= ((uint32_t)RCC_CR_HSEON);  
  121.   do
  122.   {
  123.     // RCC_CR_HSERDY=0x00020000,针对RCC_CR,HSERDY[17]外部高速时钟就绪标志,为1时,表示外部4-16MHz振荡器就绪
  124.     HSEStatus = RCC->CR & RCC_CR_HSERDY;  // 如果RCC_CR第[17]=1,那么HSEStatus=1
  125.     StartUpCounter++;  
  126.   }
  127.   // 当HSEStatus=1或StartUpCounter=0x0500时,跳出循环,while循环后面加;表示空循环
  128.   while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
  129.   if ((RCC->CR & RCC_CR_HSERDY) != RESET)  // 当RCC_CR第[17]位HSERDY=1时执行if里面的函数
  130.   {
  131.     HSEStatus = (uint32_t)0x01;
  132.   }
  133.   else
  134.   {
  135.     HSEStatus = (uint32_t)0x00;
  136.   }  
  137.   if (HSEStatus == (uint32_t)0x01)
  138.   {
  139.     // FLASH_ACR_PRFTBE=0x10,针对FLASH_ACR,PRFTBS[5]预取缓冲区状态,设1,即预取缓冲区开启
  140.     FLASH->ACR |= FLASH_ACR_PRFTBE;   
  141.     // 第一步,FLASH_ACR_LATENCY=0x03,针对FLASH_ACR寄存器,[0:1]位先至0,[2:7]位不操作
  142.     FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);  
  143.     // 第二步,FLASH_ACR_LATENCY_2=0x02, 针对FLASH_ACR寄存器,[0:1]位至10,[2:7]位不操作
  144.     FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; //LATENCY[0:2]时延,设两个等待状态,当48MHz<SYSCLK≤72MHz
  145.     // RCC_CFGR_HPRE_DIV1=0x00000000,主要针对RCC_CFGR,HPRE[4:7]位设0000,对AHB预分频配置为SYSCLK不分频,HCLK=SYSCLK
  146.     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
  147.     // RCC_CFGR_PPRE2_DIV1=0x00000000,主要针对RCC_CFGR,PPRE2[11:13]位设000,对高速APB2配置为HCLK不分频,PCLK2=HCLK
  148.     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
  149.     // RCC_CFGR_PPRE1_DIV2=0x00000400,主要针对RCC_CFGR,PPRE1[8:10]位设100,对低速APB1配置为HCLK 2分频,PCLK1=HCLK/2
  150.     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
  151.     #ifdef STM32F10X_CL      
  152.       RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);               
  153.       RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 | RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
  154.       RCC->CR |= RCC_CR_PLL2ON;                 // 不执行
  155.       while((RCC->CR & RCC_CR_PLL2RDY) == 0);   // 不执行
  156.       RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);                 // 不执行
  157.       RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL9); // 不执行
  158.     #else   
  159.      /* PLL configuration:  */
  160.      /* RCC_CFGR_PLLSRC=0x00010000,RCC_CFGR_PLLXTPRE=0x00020000,RCC_CFGR_PLLMULL=0x003C0000,整合取非后,[16:21]位为000000,其余为1 */
  161.      RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
  162.      /* RCC_CFGR_PLLSRC_HSE=0x00010000,RCC_CFGR_PLLMULL9=0x001C0000
  163.      针对RCC_CFGR,[16:21]位为011101,
  164.      PLLSRC       [16]    PLL输入时钟源,        设1,    HSE时钟作为PLL输入时钟;
  165.      PLLXTPRE     [17]    HSE分频器作为PLL输入, 设0,    HSE不分频;
  166.      PLLMUL       [18:21] PLL倍频系数,          设0111, PLL 9倍频输出,PLLCLK=HSE*9=72MHz */
  167.      RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
  168.     #endif
  169.     // RCC_CR_PLLON=0x01000000,针对RCC_CR,PLLON[24]PLL使能,PLL使能
  170.     RCC->CR |= RCC_CR_PLLON;
  171.     // RCC_CR_PLLRDY=0x02000000,即RCC_CR,PLLRDY[25]PLL时钟就绪标志,0 PLL未锁定;1 PLL锁定
  172.     while((RCC->CR & RCC_CR_PLLRDY) == 0) // 若RCC_CR的[25]位为1,则跳出循环
  173.     {
  174.     }   
  175.     // RCC_CFGR_SW=0x00000003,SW[0:1]系统时钟切换,取非为00,先将RCC_CFGR的[0:1]位至00
  176.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
  177.     // RCC_CFGR_SW_PLL=0x00000002,再将RCC_CFGR的[0:1]位至10,即PLL输出作为系统时钟
  178.     RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;   
  179.     /* Wait till PLL is used as system clock source */
  180.     // RCC_CFGR_SWS=0x0000000C,当RCC_CFGR的[2:3]位为10时,跳出循环  
  181.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
  182.     {
  183.     }
  184.   }
  185.   else
  186.   {
  187.   }
  188. }
  189. #endif
复制代码

上述函数系统初始化后,时钟频率72MHz,APB1时钟频率为72MHz,APB2时钟频率36MHz,AHB时钟频率72MHz。
————————————————
版权声明:天亮继续睡

收藏 评论0 发布时间:2022-11-20 15:40

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版