STM32單片機(jī)應(yīng)用非常廣泛,官方提供了標(biāo)準(zhǔn)的接口庫,用戶可以不用直接操作寄存器,只需要調(diào)用接口函數(shù)就可以了。在官方庫中有一個(gè)非常重要的函數(shù)void SystemInit (void),
該函數(shù)用戶可能不會(huì)直接調(diào)用,而在啟動(dòng)文件中一定會(huì)調(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.官方寄存器配置詳解截圖:


編譯條件宏定義
#ifndef STM32F10X_CL RCC->CFGR = (uint32_t)0xF8FF0000; #else RCC->CFGR = (uint32_t)0xF0FF0000; #endif /* STM32F10X_CL */
這個(gè)條件編譯是根據(jù)芯片容量不同默認(rèn)初始化CFGR寄存器(Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits )。

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 */
這個(gè)條件編譯塊的作用為根據(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
這個(gè)條件編譯塊的作用為初始化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ù)就是通過判斷定義了哪個(gè)宏定義標(biāo)志符而調(diào)用不同的設(shè)置sys時(shí)鐘頻率的函數(shù),官方固件庫默認(rèn)定義了SYSCLK_FREQ_72MHz,所以會(huì)調(diào)用SetSysClockTo72這個(gè)函數(shù)。
如果要使用其它頻率,那就解開相應(yīng)注釋(只保留一個(gè)不被注釋)。
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 */
}
}
這個(gè)函數(shù)體比較長(zhǎng),但仔細(xì)看會(huì)發(fā)現(xiàn)這個(gè)函數(shù)就是在配置CR,CFGR,ACR(設(shè)置FLASH)寄存器的某些位(使能,判斷是否就緒,設(shè)置相應(yīng)位,設(shè)置FLASH,設(shè)置AHB,APB預(yù)分頻系數(shù),設(shè)置HCLK,PCLK等等外設(shè)時(shí)鐘,設(shè)置PLL鎖相環(huán)倍頻系數(shù)最終確定系統(tǒng)時(shí)鐘),結(jié)合官方注釋和官方寄存器的說明很容易理解。
至此,SystemInit函數(shù)就能大概理解了。但是還有一個(gè)問題需要注意:那就是雖然我們?cè)趍ain函數(shù)中并沒有調(diào)用SystemInit函數(shù),但它在start up啟動(dòng)文件中被調(diào)用了:

可以看到SystemInit函數(shù)是在main函數(shù)之前執(zhí)行的,要是自定義該函數(shù),那這里也要修改名稱,建議不要隨意修改或者重構(gòu)該函數(shù)。
審核編輯:彭菁
-
接口
+關(guān)注
關(guān)注
33文章
9330瀏覽量
155749 -
STM32
+關(guān)注
關(guān)注
2301文章
11103瀏覽量
370091 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4402瀏覽量
66569 -
代碼
+關(guān)注
關(guān)注
30文章
4927瀏覽量
72550
發(fā)布評(píng)論請(qǐng)先 登錄
STM32學(xué)習(xí)筆記1 基于STM32F103的SystemInit()函數(shù)詳解
SystemInit()函數(shù)到底做了哪些操作
SystemInit()函數(shù)到底做了哪些操作
SystemInit函數(shù)的功能是什么
STM32庫函數(shù)代碼自動(dòng)生成器V1.2
STM32庫函數(shù)代碼自動(dòng)生成器正式版
STM32 IAR的庫函數(shù)資料免費(fèi)下載
STM32的SystemInit()和SetSysClock()函數(shù)詳解——學(xué)習(xí)筆記(4)
stm32下標(biāo)準(zhǔn)庫函數(shù)與HAL庫函數(shù)編程方式的差異
STM32入門-STM32時(shí)鐘系統(tǒng),時(shí)鐘初始化配置函數(shù)
基于標(biāo)準(zhǔn)庫函數(shù)與基于HAL庫函數(shù)的stm32編程方式對(duì)比
STM32庫函數(shù)開發(fā)-GPIO
STM32庫函數(shù)SystemInit()詳解

STM32庫函數(shù)SystemInit()詳解
評(píng)論