天天看點

STM32F1 時鐘樹STM32F1 時鐘樹

STM32F1 時鐘樹

參考:《【野火®】零死角玩轉STM32—F103指南者》

STM32F1 時鐘樹STM32F1 時鐘樹

時鐘源

  1. HSI:高速内部時鐘,RC振蕩器,頻率為8MHz
  2. HSE:高速外部時鐘,可接石英/陶瓷諧振器,或者接外部時鐘源,頻率範圍為4MHz~16MHz
  3. LSI:低速内部時鐘,RC振蕩器,頻率為40kHz
  4. LSE:低速外部時鐘,接頻率為32.768kHz的石英晶體
  • LSI可以用于驅動獨立看門狗和通過程式選擇驅動RTC。RTC用于從停機/待機模式下自動喚醒系統。LSE也可用來通過程式選擇驅動RTC。
  • 内部即指晶片已經內建,外部即指需要設計PCB時接入
  • 鎖相環:這個東西可以将輸入頻率進行放大然後輸出,比如說輸入1MHz,設定倍頻為3倍,最後就能輸出3MHz的信号。STM32的鎖相環倍頻輸出,其時鐘輸入源可選擇為HSI/2、HSE或者HSE/2。倍頻可選擇為2~16倍,但是其輸出頻率最大不得超過72MHz。

時鐘配置

主要

SYSCLK:系統時鐘

HCLK:AHB總線時鐘

PCLK2:APB2總線時鐘

PCLK1:APB1總線時鐘

庫函數的标準配置:PCLK2 = HCLK = SYSCLK = PLLCLK = 72M,PCLK1 = HCLK/2 = 36M

APB1和APB2搭載的外設如下圖所示:

STM32F1 時鐘樹STM32F1 時鐘樹

其它

USB時鐘

USB 時鐘是由 PLLCLK 經過 USB 預分頻器得到,分頻因子可以是:[1,1.5],具體的由時鐘配置寄存器 CFGR 的位 22:USBPRE 配置。USB 的時鐘最高是 48M,根據分頻因子反推過來算,PLLCLK 隻能是 48M 或者是 72M。一般我們設定 PLLCLK=72M,USBCLK=48M。USB 對時鐘要求比較高,是以 PLLCLK 隻能是由 HSE 倍頻得到,不能使用 HSI 倍頻。

Cortex 系統時鐘

Cortex 系統時鐘由 HCLK 8 分頻得到,等于 9M,Cortex 系統時鐘用來驅動核心的系統定時器 SysTick,SysTick 一般用于作業系統的時鐘節拍,也可以用做普通的定時。

ADC 時鐘

ADC 時鐘由 PCLK2 經過 ADC 預分頻器得到,分頻因子可以是[2,4,6,8],具體的由時鐘配置寄存器 CFGR 的位 15-14:ADCPRE[1:0]決定。很奇怪的是怎麼沒有 1 分頻。ADC時鐘最高隻能是 14M,如果采樣周期設定成最短的 1.5 個周期的話,ADC 的轉換時間可以達到最短的 1us。如果真要達到最短的轉換時間 1us 的話,那 ADC 的時鐘就得是 14M,反推 PCLK2 的時鐘隻能是:28M、56M、84M、112M,鑒于 PCLK2 最高是 72M,是以隻能取 28M 和 56M。

RTC 時鐘、獨立看門狗時鐘

RTC 時鐘可由 HSE/128 分頻得到,也可由低速外部時鐘信号 LSE 提供,頻率為32.768KHZ,也可由低速内部時鐘信号 HSI 提供,具體選用哪個時鐘由備份域控制寄存器BDCR 的位 9-8:RTCSEL[1:0]配置。獨立看門狗的時鐘由 LSI 提供,且隻能是由 LSI 提供,LSI 是低速的内部時鐘信号,頻率為 30~60KHZ 直接不等,一般取 40KHZ。

MCO 時鐘輸出

MCO 是 microcontroller clock output 的縮寫,是微控制器時鐘輸出引腳,在 STM32 F1系列中 由 PA8 複用所得,主要作用是可以對外提供時鐘,相當于一個有源晶振。MCO 的時鐘來源可以是:PLLCLK/2、HSI、HSE、SYSCLK,具體選哪個由時鐘配置寄存器CFGR 的位 26-24:MCO[2:0]決定。除了對外提供時鐘這個作用之外,我們還可以通過示波器監控 MCO 引腳的時鐘輸出來驗證我們的系統時鐘配置是否正确。

基于标準庫的設定代碼

使用标準庫的模闆工程,在系統啟動的時候,statup_stm32f10x_hd.s 已經調用 SystemInit()函數把系統時鐘初始化成 72MHZ,SystemInit()在庫檔案:system_stm32f10x.c 中定義。然後再進入main函數。

如果我們想把系統時鐘設定低一點或者超頻的話,可以修改底層的庫檔案,即改動SystemInit()函數。但是為了維持庫的完整性,可以在按照标準庫的方法啟動後進入main函數中時,再自己寫個時鐘初始化函數将系統時鐘重新配置。

HSI 設定系統時鐘函數跟 HSE 設定系統時鐘函數在原理上是一樣的,有一個差別的地方就是,HSI 必須 2 分頻之後才能作為 PLL 的時鐘來源,是以使用 HSI 時,最大的系統時鐘 SYSCLK 隻能是 HSI/216=416=64MHZ。

void HSE_SetSysClock(uint32_t pllmul)
{
    volatile uint32_t StartUpCounter = 0, HSEStartUpStatus = 0;
    RCC_DeInit();         //重設RCC寄存器為預設值
    RCC_HSEConfig(RCC_HSE_ON);   //使能HSE
    
    do
  	{
    HSEStartUpStatus = RCC_WaitForHSEStartUp();
    StartUpCounter++;  
  	} while((HSEStartUpStatus == 0) && (StartUpCounter != 9));//等待 HSE 啟動穩定
     
    if ( RCC_WaitForHSEStartUp() != 0)  //等待使能成功
  	{    	
//-----------------------------------------------------------------//
// 這兩句是操作 FLASH 閃存用到的,如果不操作 FLASH,這兩個注釋掉也沒影響
// 使能 FLASH 預存取緩沖區
	FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
// SYSCLK 周期與閃存通路時間的比例設定,這裡統一設定成 2
// 設定成 2 的時候,SYSCLK 低于 48M 也可以工作,如果設定成 0 或者 1 的時候,
// 如果配置的 SYSCLK 超出了範圍的話,則會進入硬體錯誤,程式就死了
// 0:0 < SYSCLK <= 24M
// 1:24< SYSCLK <= 48M
// 2:48< SYSCLK <= 72M
	FLASH_SetLatency(FLASH_Latency_2);
//-----------------------------------------------------------------//
     
    // AHB預分頻因子設定為1分頻,HCLK = SYSCLK 
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 
    // APB2預分頻因子設定為1分頻,PCLK2 = HCLK
    RCC_PCLK2Config(RCC_HCLK_Div1); 
    // APB1預分頻因子設定為1分頻,PCLK1 = HCLK/2 
    RCC_PCLK1Config(RCC_HCLK_Div2);

//-----------------設定各種頻率主要就是在這裡設定-------------------//
    // 設定PLL時鐘來源為HSE,設定PLL倍頻因子
     // PLLCLK = 8MHz * pllmul
	RCC_PLLConfig(RCC_PLLSource_HSE_Div1, pllmul);
//------------------------------------------------------------------//

    // 開啟PLL 
    RCC_PLLCmd(ENABLE);
    // 等待 PLL穩定
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
    // 讀取時鐘切換狀态位,確定PLLCLK被選為系統時鐘
    while (RCC_GetSYSCLKSource() != 0x08);
       
   }
    else
    {
       // 當HSE開啟失敗或者故障的時候,單片機會自動把HSI設定為系統時鐘,HSI是内部的高速時鐘,8MHZ
       // 如果HSE開啟失敗,可在這裡添加出錯的代碼處理
    }
    
}

           

MCO配置

/*
 * 初始化MCO引腳PA8
 * 在F1系列中MCO引腳隻有一個,即PA8,在F4系列中,MCO引腳會有兩個
 */
void MCO_GPIO_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	// 開啟GPIOA的時鐘
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	// 選擇GPIO8引腳
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	
	//設定為複用功能推挽輸出
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	
	//設定IO的翻轉速率為50M
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	// 初始化GPIOA8
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}

           
int main(void)
{	
	
	HSE_SetSysClock(RCC_PLLMul_9);
	MCO_GPIO_Config();// MCO 引腳初始化
		
	RCC_MCOConfig(RCC_MCO_SYSCLK);		     // 72M  
	
	while (1)
	{
		
	}

}
           

繼續閱讀