STM32時鐘學習
- 複位
-
- 程式設計控制系統複位
- ? 使用者選擇位元組的進一步資訊,請參考STM32F10xxx閃存程式設計手冊。
- 時鐘樹簡圖
-
- 實際的寄存器操作
-
- (1)對RCC_CR寄存器進行設定
- (2)時鐘配置寄存器(RCC_CFGR)
- (3)RCC PLL configuration register (RCC_PLLCFGR)
- (4)RCC clock interrupt register (RCC_CIR)
- (5)RCC AHB1 peripheral reset register (RCC_AHB1RSTR)複位
- (6)RCC AHB1 peripheral clock register (RCC_AHB1ENR)使能
- (7)備份域控制寄存器 (RCC_BDCR)
- 代碼學習
f(VCO clock) = f(PLL clock input) × (PLLN / PLLM)
f(PLL general clock output) = f(VCO clock) / PLLP
f(USB OTG FS, SDIO, RNG clock output) = f(VCO clock) / PLLQ
PLLN with 192 ≤ PLLN ≤ 432
PLLM with 2 ≤ PLLM ≤ 63
PLLP = 2, 4, 6, or 8
4 <= PLLQ <= 15
複位
支援三種複位形式,分别為系統複位、上電複位和備份區域複位。
電源複位:除了備份區域外的所有寄存器
系統複位:除了時鐘控制器的RCC_CSR寄存器中的複位标志位和備份區域中的寄存器以外的所有寄存器
備份區域複位:隻影響備份區域
産生電源複位的事件:
- 上電/掉電複位(POR/PDR複位)
- 從待機模式中傳回
産生備份區域複位的事件:
- 軟體複位,備份區域複位可由設定備份域控制寄存器 (RCC_BDCR)中的BDRST位産生。
- 在VDD和VBAT兩者掉電的前提下,VDD或VBAT上電将引發備份區域複位
産生一個系統複位的事件:
- NRST引腳上的低電平(外部複位)
- 視窗看門狗計數終止(WWDG複位)
- 獨立看門狗計數終止(IWDG複位)
- 軟體複位(SW複位)
- 低功耗管理複位
程式設計控制系統複位
我們所能控制的隻有系統複位
(1)可通過檢視RCC_CSR控制狀态寄存器中的複位狀态标志位識别複位事件來源。
(2)軟體的方式進行系統複位:通過将Cortex™-M3中斷應用和複位控制寄存器中的SYSRESETREQ位置’1’
(3)低功耗管理複位
在以下兩種情況下可産生低功耗管理複位:
在進入待機模式時産生低功耗管理複位:
通過将使用者選擇位元組中的nRST_STDBY位置’1’将使能該複位。這時,即使執行了進入待
機模式的過程,系統将被複位而不是進入待機模式。
在進入停止模式時産生低功耗管理複位:
通過将使用者選擇位元組中的nRST_STOP位置’1’将使能該複位。這時,即使執行了進入停機
模式的過程,系統将被複位而不是進入停機模式。
? 使用者選擇位元組的進一步資訊,請參考STM32F10xxx閃存程式設計手冊。
時鐘樹簡圖
STM32為了低功耗,将所有的外設時鐘都設定為disable。使用外設,需要打開對應時鐘。
看圖了解時鐘源—>系統時鐘來源—>各個外設時鐘

三種不同的時鐘源可被用來驅動系統時鐘(SYSCLK): HSI振蕩器時鐘、 HSE振蕩器時鐘、 PLL時鐘(内部PLL可以用來倍頻HSI RC的輸出時鐘或HSE晶體輸出時鐘)。
這些裝置有40kHz低速内部RC、32.768kHz低速外部晶體2種二級時鐘源,當不被使用時,任一個時鐘源都可被獨立地啟動或關閉,由此優化系統功耗。
實際的寄存器操作
(1)對RCC_CR寄存器進行設定
Reset value: 0x0000 XX83 where X is undefined.
STM32F207支援一種專用的PLL(PLLI2S),用于在I2S接口上生成精确的時鐘,以實作高品質的音頻性能。
(2)時鐘配置寄存器(RCC_CFGR)
Reset value: 0x0000 0000
(3)RCC PLL configuration register (RCC_PLLCFGR)
Address offset: 0x04
Reset value: 0x24003010
該寄存器用于根據公式配置鎖相環時鐘輸出
(4)RCC clock interrupt register (RCC_CIR)
(5)RCC AHB1 peripheral reset register (RCC_AHB1RSTR)複位
(6)RCC AHB1 peripheral clock register (RCC_AHB1ENR)使能
當外設時鐘沒有啟用時,軟體不能讀出外設寄存器的數值,傳回的數值始終是0x0。
(7)備份域控制寄存器 (RCC_BDCR)
代碼學習
沒有打開任何外設時鐘的代碼學習
或操作開,與操作關
開HSI
關HSE、CSS、PLL
關HSEBYP
開HSE
不同應用下,時鐘頻率的選擇和使用過程中出現誤差的一個校準(配置對應寄存器)
系統複位後,HSI振蕩器被選為系統時鐘。當時鐘源被直接或通過PLL間接作為系統時鐘時,它将不能被停止。隻有當目标時鐘源準備就緒了(經過啟動穩定階段的延遲或PLL穩定),從一個時鐘源到另一個時鐘源的切換才會發生。在被選擇時鐘源沒有就緒時,系統時鐘的切換不會發生。直至目标時鐘源就緒,才發生切換。在時鐘控制寄存器(RCC_CR)裡的狀态位訓示哪個時鐘已經準備好了,哪個時鐘目前被用作系統時鐘。通過設定備份域控制寄存器(RCC_BDCR)裡的RTCSEL[1:0]位,RTCCLK時鐘源可以由HSE/128、LSE或LSI時鐘提供。除非備份域複位,此選擇不能被改變。
/*********************************系統初始化*************************************/
/* PLL (clocked by HSE) used as System clock source */
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* 其他不變,HSION=1 */
RCC->CR |= (uint32_t)0x00000001;
/* Reset CFGR register */
RCC->CFGR = 0x00000000;
/* 其他不變,HSEON, CSSON, PLL OFF*/
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x24003010;
/* 其他不變,HSEBYP off */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Disable all interrupts */
RCC->CIR = 0x00000000;
/* 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)
{
/* HCLK = SYSCLK / 1*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK / 2*/
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
/* PCLK1 = HCLK / 4*/
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
/* Configure the main PLL */
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
/* Enable the main PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till the main PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_3WS;
/* Select the main PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_PLL;
/* Wait till the main PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
{
}
}
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 */
}