天天看點

RCC—使用HSE配置系統時鐘RCC—使用HSE配置系統時鐘

RCC—使用HSE配置系統時鐘

晶片提供時鐘就要有時鐘樹

時鐘樹在參考手冊RCC章節開頭就有(這裡的時鐘樹看到感覺眼睛打了馬賽克,小弟截圖技術有限)

RCC—使用HSE配置系統時鐘RCC—使用HSE配置系統時鐘

什麼是晶振?

晶振:晶體振蕩器,用于各種電路中産生振蕩頻率,每個單片機裡都會有晶振,給單片機提供時鐘頻率,振蕩得越快,時鐘頻率就越高,單片機運作的速度就越快

解析時鐘樹的方法:(系統時鐘)

  1. 時鐘是由晶振提供的,首先要找到時鐘的入口點。圖中OSC_IN 和 OSC_OUT,這兩個是外部晶振的引腳,是以時鐘是從這裡進入的。接有源晶振時,時鐘從OSC_IN進入,OSC_OUT懸空。接無源晶振時,時鐘從OSC_IN 和 OSC_OUT一起進入
  2. 時鐘進入以後會經過PLL鎖相環,進入前會經過一個M分頻,進入PLL鎖相環之後就會進入N倍頻,輸出時經過一個P分頻,輸出的時鐘為PLLCLK
  3. 可以選擇PLLCLK、HSE、HIS作為系統時鐘
  4. 然後經過AHB總線的分頻因子,成為HCLK作為AHB總線的時鐘,或者再經過APB的分頻因子作為APB1、APB2總線的時鐘(根據參考手冊AHB總線頻率最大為180MHZ 、高速APB2總線頻率最大為90MHZ 低速APB1總線頻率最大為45MHZ)

    上述分析的是時鐘樹的系統時鐘,還有其他時鐘RTC實時時鐘、看門狗時鐘、I2S時鐘、以太網時鐘、MCO輸出時鐘,這些等需要用到的時鐘看吧

下面用固件庫編寫使用HSE配置系統時鐘函數

(HSI也是同樣的思路)

  1. 啟動HSE,在頭檔案尋找HSE啟動的函數void RCC_HSEConfig(uint8_t RCC_HSE)
  2. 等待HSE穩定ErrorStatus RCC_WaitForHSEStartUp(void)

    這個函數是如何實作的:在這個函數中還調用了函數

    FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG)

    那先講解這個函數是如何實作的:這個函數的功能是檢查是否設定了指定的RCC标志。RCC的标志(RCC_FLAG)都會有自己的值,首先檢查參數,然後得到RCC寄存器的位号(根據RCC的标志确定在RCC的哪個寄存器裡),最後獲得RCC寄存器的位置判斷是否設定了指定的參數,然後傳回值,如果設定了傳回1,否傳回0

    判斷HSE是否準備好,如果是傳回1,否傳回0

  3. 設定HCLK、APB1、APB2預分頻因子

    void RCC_HCLKConfig(uint32_t RCC_SYSCLK)

    void RCC_PCLK1Config(uint32_t RCC_HCLK)

    void RCC_PCLK2Config(uint32_t RCC_HCLK)

  4. 設定進入PLL鎖相環的M分頻因子 PLL鎖相環的N倍頻因子 出PLL鎖相環的P分頻因子 void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t PLLM, uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ)控制系統時鐘的頻率就在于這幾個分頻因子
  5. 啟動PLL void RCC_PLLCmd(FunctionalState NewState)

    等待PLL穩定 使用了FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG)把RCC_FLAG設為RCC_FLAG_PLLRDY,若準備好傳回1

  6. 設定PLLCLK為系統時鐘void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource)
  7. 讀取狀态位確定PLLCLK被選中為系統時鐘

    uint8_t RCC_GetSYSCLKSource(void)//該函數功能:傳回時鐘源用作系統時鐘

    若傳回數值為PLLCLK數值,則PLLCLK被選為系統時鐘

代碼如下

函數的形參根據函數中需要傳入的資料所設定

void HSE_SetSysclk ( uint32_t PLLM, uint32_t PLLN, uint32_t PLLP, uint32_t PLLQ)
			{
			    RCC_HSEConfig(RCC_HSE_ON);
			    if(RCC_WaitForHSEStartUp()==SUCCESS)
			    {
			        RCC_HCLKConfig(RCC_SYSCLK_Div1);
			        RCC_PCLK1Config(RCC_HCLK_Div4);
			        RCC_PCLK2Config(RCC_HCLK_Div2);
			        RCC_PLLConfig(RCC_PLLSource_HSE,PLLM, PLLN, PLLP, PLLQ);
			        RCC_PLLCmd(ENABLE);
			        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET);
			        
			        
			        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
			        while(RCC_GetSYSCLKSource()!=0x08);
			    }
			    else
			    {
			        while(1)
			        {
			            
			        }
			    }
			}
           

繼續閱讀