0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

STM32庫函數(shù)SystemInit()詳解

jf_pJlTbmA9 ? 來源:jf_pJlTbmA9 ? 作者:jf_pJlTbmA9 ? 2023-09-18 15:45 ? 次閱讀

STM32單片機(jī)應(yīng)用非常廣泛,官方提供了標(biāo)準(zhǔn)的接口庫,用戶可以不用直接操作寄存器,只需要調(diào)用接口函數(shù)就可以了。在官方庫中有一個非常重要的函數(shù)void SystemInit (void),

該函數(shù)用戶可能不會直接調(diào)用,而在啟動文件中一定會調(diào)用。函數(shù)原型如下:

函數(shù)原型

void SystemInit (void)
{
  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
  /* Set HSION bit */
  RCC->CR |= (uint32_t)0x00000001;

  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
  RCC->CFGR  = (uint32_t)0xF8FF0000;
#else
  RCC->CFGR  = (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */   
  
  /* Reset HSEON, CSSON and PLLON bits */
  RCC->CR  = (uint32_t)0xFEF6FFFF;

  /* Reset HSEBYP bit */
  RCC->CR  = (uint32_t)0xFFFBFFFF;

  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
  RCC->CFGR  = (uint32_t)0xFF80FFFF;

#ifdef STM32F10X_CL
  /* Reset PLL2ON and PLL3ON bits */
  RCC->CR  = (uint32_t)0xEBFFFFFF;

  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x00FF0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;      
#else
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */
    
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
  #ifdef DATA_IN_ExtSRAM
    SystemInit_ExtMemCtl(); 
  #endif /* DATA_IN_ExtSRAM */
#endif 

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

#ifdef VECT_TAB_SRAM
  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif 
}

可以看到函數(shù)體中幾乎全是條件編譯。

(1)先看第一行代碼:RCC->CR |= (uint32_t)0x00000001;顯然這是給CR寄存器的最低一位賦值為1.官方寄存器配置詳解截圖:

poYBAGIB2VOAGnwMAAMoC0MFciA571.png
pYYBAGIB2VWAKHq_AAKG7PP3AUs272.png

編譯條件宏定義

#ifndef STM32F10X_CL
  RCC->CFGR  = (uint32_t)0xF8FF0000;
#else
  RCC->CFGR  = (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */   

這個條件編譯是根據(jù)芯片容量不同默認(rèn)初始化CFGR寄存器(Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits )。

poYBAGIB2VeAQoQ9AAPmr-3FLb8441.png

 RCC->CR  = (uint32_t)0xFEF6FFFF;
 RCC->CR  = (uint32_t)0xFFFBFFFF;

顯然是把CR寄存器的某些位賦值,其作用為:Reset HSEON, CSSON and PLLON ,HSEBYPbits即將HSEON,CSSON,PLLON,HSEBYP位置為零。

/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC->CFGR  = (uint32_t)0xFF80FFFF;

作用為把CFGR寄存器的PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE位置0。

#ifdef STM32F10X_CL
  /* Reset PLL2ON and PLL3ON bits */
  RCC->CR  = (uint32_t)0xEBFFFFFF;

  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x00FF0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;

  /* Reset CFGR2 register */
  RCC->CFGR2 = 0x00000000;      
#else
  /* Disable all interrupts and clear pending bits  */
  RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */

這個條件編譯塊的作用為根據(jù)芯片容量初始化中斷位(關(guān)閉中斷)。

#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
  #ifdef DATA_IN_ExtSRAM
  SystemInit_ExtMemCtl(); 
  #endif /* DATA_IN_ExtSRAM */
#endif 

這個條件編譯塊的作用為初始化Memory控制。

static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSE
  SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
  SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
  SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
  SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
  SetSysClockTo56();  
#elif defined SYSCLK_FREQ_72MHz
  SetSysClockTo72();
#endif
 
 /* If none of the define above is enabled, the HSI is used as System clock
    source (default after reset) */ 
}

我們可以看到該函數(shù)就是通過判斷定義了哪個宏定義標(biāo)志符而調(diào)用不同的設(shè)置sys時鐘頻率的函數(shù),官方固件庫默認(rèn)定義了SYSCLK_FREQ_72MHz,所以會調(diào)用SetSysClockTo72這個函數(shù)。

如果要使用其它頻率,那就解開相應(yīng)注釋(只保留一個不被注釋)。

SetSysClockTo72()函數(shù)如下:

static void SetSysClockTo72(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    
  /* Enable HSE */    
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  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)
  {
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;

    /* Flash 2 wait state */
    FLASH->ACR  = (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;    

 
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
    
    /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

#ifdef STM32F10X_CL
    /* Configure PLLs ------------------------------------------------------*/
    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
        
    RCC->CFGR2  = (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                             RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
  
    /* Enable PLL2 */
    RCC->CR |= RCC_CR_PLL2ON;
    /* Wait till PLL2 is ready */
    while((RCC->CR   RCC_CR_PLL2RDY) == 0)
    {
    }
    
   
    /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ 
    RCC->CFGR  = (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
                            RCC_CFGR_PLLMULL9); 
#else    
    /*  PLL configuration: 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);
#endif /* STM32F10X_CL */

    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till PLL is ready */
    while((RCC->CR   RCC_CR_PLLRDY) == 0)
    {
    }
    
    /* Select PLL as system clock source */
    RCC->CFGR  = (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR   (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock 
         configuration. User can add here some code to deal with this error */
  }
}

這個函數(shù)體比較長,但仔細(xì)看會發(fā)現(xiàn)這個函數(shù)就是在配置CR,CFGR,ACR(設(shè)置FLASH)寄存器的某些位(使能,判斷是否就緒,設(shè)置相應(yīng)位,設(shè)置FLASH,設(shè)置AHB,APB預(yù)分頻系數(shù),設(shè)置HCLK,PCLK等等外設(shè)時鐘,設(shè)置PLL鎖相環(huán)倍頻系數(shù)最終確定系統(tǒng)時鐘),結(jié)合官方注釋和官方寄存器的說明很容易理解。

至此,SystemInit函數(shù)就能大概理解了。但是還有一個問題需要注意:那就是雖然我們在main函數(shù)中并沒有調(diào)用SystemInit函數(shù),但它在start up啟動文件中被調(diào)用了:

pYYBAGIB2VmAKJ23AADqsNTSO84400.png

可以看到SystemInit函數(shù)是在main函數(shù)之前執(zhí)行的,要是自定義該函數(shù),那這里也要修改名稱,建議不要隨意修改或者重構(gòu)該函數(shù)。

審核編輯:彭菁

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 接口
    +關(guān)注

    關(guān)注

    33

    文章

    8254

    瀏覽量

    149942
  • STM32
    +關(guān)注

    關(guān)注

    2257

    文章

    10828

    瀏覽量

    352433
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4235

    瀏覽量

    61965
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4670

    瀏覽量

    67760
收藏 人收藏

    評論

    相關(guān)推薦

    STM32學(xué)習(xí)筆記1 基于STM32F103的SystemInit()函數(shù)詳解

    本帖最后由 zhangshun5233 于 2015-1-20 11:37 編輯 STM32學(xué)習(xí)筆記1 基于STM32F103的SystemInit()函數(shù)
    發(fā)表于 01-20 11:30

    SystemInit()函數(shù)到底做了哪些操作

    使用庫函數(shù)編寫的LED程序,在system_stm32f10x.c文件中可以找到SystemInit()函數(shù),SystemInit()代碼如
    發(fā)表于 08-10 07:53

    SystemInit()函數(shù)到底做了哪些操作

    使用庫函數(shù)編寫的LED程序,在system_stm32f10x.c文件中可以找到SystemInit()函數(shù),SystemInit()代碼如
    發(fā)表于 08-12 06:21

    SystemInit函數(shù)的功能是什么

    對system_stm32f4xx的理解上一篇博客解釋了stm32的啟動文件,在啟動文件中,在進(jìn)入__mainC庫函數(shù)之前,進(jìn)入了SystemInit
    發(fā)表于 08-24 08:09

    PICC庫函數(shù)詳解

    PICC庫函數(shù)詳解
    發(fā)表于 04-18 20:13 ?132次下載

    STM32庫函數(shù)代碼自動生成器V1.2

    stm32庫函數(shù)代碼自動生成器是STM32學(xué)習(xí)的小工具。 stm32庫函數(shù)代碼自動生成器可以根據(jù)你的配置生成相應(yīng)的
    發(fā)表于 06-17 17:55 ?0次下載

    STM32庫函數(shù)代碼自動生成器正式版

    STM32庫函數(shù)代碼自動生成器正式版 STM32庫函數(shù)代碼自動生成器正式版
    發(fā)表于 07-25 18:52 ?0次下載

    STM32 IAR的庫函數(shù)資料免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是STM32 IAR的庫函數(shù)資料免費(fèi)下載。
    發(fā)表于 03-27 09:48 ?43次下載
    <b class='flag-5'>STM32</b> IAR的<b class='flag-5'>庫函數(shù)</b>資料免費(fèi)下載

    STM32F4 HAL庫函數(shù)說明下載

    STM32F4 HAL庫函數(shù)說明下載
    發(fā)表于 05-26 09:27 ?73次下載

    STM32SystemInit()和SetSysClock()函數(shù)詳解——學(xué)習(xí)筆記(4)

    文章內(nèi)容根據(jù)野火學(xué)習(xí)教程進(jìn)行整理,僅僅是學(xué)習(xí)記錄。野火的教程把SetSysClock()函數(shù)的內(nèi)容講解了一下,學(xué)會了怎么查手冊怎么看。我打算從SystemInit()開始分析,畢竟是第一個被調(diào)用的C
    發(fā)表于 11-26 09:51 ?20次下載
    <b class='flag-5'>STM32</b>的<b class='flag-5'>SystemInit</b>()和SetSysClock()<b class='flag-5'>函數(shù)</b><b class='flag-5'>詳解</b>——學(xué)習(xí)筆記(4)

    stm32下標(biāo)準(zhǔn)庫函數(shù)與HAL庫函數(shù)編程方式的差異

    stm32下標(biāo)準(zhǔn)庫函數(shù)與HAL庫函數(shù)編程方式的差異標(biāo)準(zhǔn)庫函數(shù)HAL庫函數(shù)標(biāo)準(zhǔn)庫函數(shù)與HAL
    發(fā)表于 12-09 14:21 ?15次下載
    <b class='flag-5'>stm32</b>下標(biāo)準(zhǔn)<b class='flag-5'>庫函數(shù)</b>與HAL<b class='flag-5'>庫函數(shù)</b>編程方式的差異

    STM32入門-STM32時鐘系統(tǒng),時鐘初始化配置函數(shù)

    使用庫函數(shù)編寫的LED程序,在system_stm32f10x.c文件中可以找到SystemInit()函數(shù),SystemInit()代碼如
    發(fā)表于 12-27 19:07 ?2次下載
    <b class='flag-5'>STM32</b>入門-<b class='flag-5'>STM32</b>時鐘系統(tǒng),時鐘初始化配置<b class='flag-5'>函數(shù)</b>

    基于標(biāo)準(zhǔn)庫函數(shù)與基于HAL庫函數(shù)stm32編程方式對比

    以實(shí)例程序(串口通信),分析基于標(biāo)準(zhǔn)庫函數(shù)與基于HAL庫函數(shù)stm32編程方式的差異一、基于標(biāo)準(zhǔn)庫函數(shù)stm32編程方式二、基于HAL
    發(fā)表于 12-28 19:09 ?30次下載
    基于標(biāo)準(zhǔn)<b class='flag-5'>庫函數(shù)</b>與基于HAL<b class='flag-5'>庫函數(shù)</b>的<b class='flag-5'>stm32</b>編程方式對比

    STM32庫函數(shù)開發(fā)-GPIO

    2021-01-11 學(xué)習(xí)日志STM32f1庫函數(shù)開發(fā)學(xué)習(xí)實(shí)戰(zhàn)一 · I/O口1. 文件夾結(jié)構(gòu)2. 配置細(xì)節(jié) · 從寄存器到庫函數(shù)3. 跑馬燈4. 按鍵輸入STM32f1
    發(fā)表于 01-13 16:17 ?14次下載
    <b class='flag-5'>STM32</b><b class='flag-5'>庫函數(shù)</b>開發(fā)-GPIO

    STM32庫函數(shù)SystemInit()詳解

    STM32單片機(jī)應(yīng)用非常廣泛,官方提供了標(biāo)準(zhǔn)的接口庫,用戶可以不用直接操作寄存器,只需要調(diào)用接口函數(shù)就可以了。
    發(fā)表于 02-08 15:20 ?3次下載
    <b class='flag-5'>STM32</b><b class='flag-5'>庫函數(shù)</b><b class='flag-5'>SystemInit</b>()<b class='flag-5'>詳解</b>