跟蹤進入該函數,可見一連串的條件編譯:
?
單步運行,執行的是:
#elif defined SYSCLK_FREQ_72MHz
SetSysClockTo72();
為何執行該行呢,找到SYSCLK_PREQ_**的相關定義,如下圖所示。
這樣就得到了我們所要的一個結論:如果要更改系統工作頻率,只需要在這里更改就可以了。
可以繼續跟蹤進入這個函數來觀察如何將工作頻率設定為72MHz的。
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);
//開啟HSE
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC-》CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
//等待HSE確實可用,這有個標志,即RCC_CR寄存器中的HSERDY位(bit 17),這個等待不會無限長,有個超時策略,即每循環一次計數器加1,如果計數的次數超過HSEStartUp_TimeOut,就退出循環,而這個HSEStartUp_TimeOut在stm32f10x.h中定義,
#define HSEStartUp_TimeOut ((uint16_t)0x0500) /*!《 Time out for HSE start up */
///////////////////////////////////////////////////////////////////////////////////////////////
if ((RCC-》CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
///再次判斷HSERDY標志位,并據此給HSEStatus變量賦值。
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;
//找到定義: #define RCC_CFGR_HPRE_DIV1 ((uint32_t)0x00000000) /*!《 SYSCLK not divided */
/* PCLK2 = HCLK */
RCC-》CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
//找到定義:#define RCC_CFGR_PPRE2_DIV1 ((uint32_t)0x00000000) /*!《 HCLK not divided */
/* PCLK1 = HCLK */
RCC-》CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
//找到定義:#define RCC_CFGR_PPRE1_DIV2 ((uint32_t)0x00000400) /*!《 HCLK divided by 2 */
#ifdef STM32F10X_CL
……
#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 */
//以上是設定PLL的倍頻系數為9,也就是說,這個72M是在外部晶振為8M時得到的。
/* 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 */
/* Go to infinite loop */
while (1)
{
}
}
}
至此,我們可以歸納幾條:
(1) 時鐘源有3個
(2) 開機時默認是HSI起作用,可以配置為所要求的任意一個時鐘
(3) 配置時必須按一定的順序來打開或都關閉一些位,并且各時鐘起作用有一定的時間,因此要利用芯片內部的標志位來判斷是否可以執行下一步。
(4) 如果外部時鐘、PLL輸出失效,系統可以自動回復到HSI(開啟時鐘安全系統)
(5) HSI的頻率準確度可以達到+/- 1%,如果有必要時,還可以用程序來調整這個頻率,可調的范圍大致在200KHz左右。
最后讓我們來感受一下勞動的果實吧--試著改改頻率看有何反應。
為查看更改后的效果,先記錄更改前的數據。將調試切換到仿真,在第一條:
Delay(0xAFFFF);
指令執行前后,分別記錄下Status和Sec
Status:2507 3606995
Sec:0.00022749 0.05028982
將振蕩頻率更改為36MHz,即
。。.
#define SYSCLK_FREQ_36MHz 36000000 //去掉該行的注釋
/* #define SYSCLK_FREQ_48MHz 48000000 */
/* #define SYSCLK_FREQ_56MHz 56000000 */
/*#define SYSCLK_FREQ_72MHz 72000000*/ //將該行加上注釋
再次運行,結果如下:
Status:2506 3606994
Sec:0.00008478 0.10036276
基本上是延時時間長了一倍。改成硬件仿真,將代碼寫入板子,可以看到LED閃爍的頻率明顯變慢了。
評論
查看更多