<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> STM32 >> 瀏覽文章

        STM32 時鐘配置

        作者:真誠冰雪天涯   來源:真誠冰雪天涯   點擊數:  更新時間:2014年06月17日   【字體:
        STM32 時鐘配置有2種方式:第一使用庫自帶的SystemInit();函數自動配置;第二種:通過stm32f10x_rcc.c文件里的函數配置,比如RCC_HCLKConfig(uint32_t RCC_SYSCLK),RCC_PCLK1Config(uint32_t RCC_HCLK),RCC_PCLK2Config(uint32_t RCC_HCLK);這種方式可以根據自己需要把HCLK、PLCK1、PLCK2配置成不同的數值。第一種方式中SystemInit()這個函數直接把SYSCLK 來源配置為PLLCK ,PCLK1=PCLK2=HCLK=SYSCLK。PLLCK 時鐘來源為外部高速晶振,具體分頻關系為HSE/2然后乘以倍頻系數(PLLMUL),比如外部晶振為8MHZ,設置工作頻率為36MHz,則PLLCK=(HSE(8)/2)*9=36MHz。工作頻率的選取根據所使用的芯片型號來確定,然后在system_stm32f10x.c函數中定義選取,如下選擇的為工作頻率36MHz。 

        #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)

        #define SYSCLK_FREQ_24MHz 24000000

        #else

        #define SYSCLK_FREQ_36MHz 36000000// 選擇系統工作頻率為36MHz

        #endif

        注意在V3.5.0以上的庫文件里SystemInit()函數已經被添加入啟動文件中了,也就是庫已經自動配置好了 HCLK(AHB總線)、PLCK1(APB1)、PLCK2(APB2)這幾個總線的時鐘頻率,一般在36MHz以下的工作頻率 HCLK=PLCK1=PLCK2=用戶選擇的工作頻率,在超過36MHz的工作頻率HCLK=PLCK2=用戶選擇的頻率,而PCKL1因為是低速總線最大只能到36MHz,所以庫自動設置PCLK=36MHz。

        在V3.5.0以下的庫中,通常在自己寫的時鐘配置使能函數里加入SystemInit(),比如我自己用的RCC_Configuration(void)如下:

        void RCC_Configuration(void)

        {

        SystemInit();//初始化系統時鐘

        RCC_ADCCLKConfig(RCC_PCLK2_Div4); //設置ADC 的工作頻率為9M 

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3| RCC_APB1Periph_TIM2, ENABLE);

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA |RCC_APB2Periph_AFIO, ENABLE);

        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

        RCC_ClockSecuritySystemCmd(ENABLE);

        }

         

        下面是從一處論壇截取的例程,配置時鐘為72MHz,使用CPU為STM32F107VC

        我已經定義了STM32F10X_CL,SYSCLK_FREQ_72MHz

        函數調用順序:

        startup_stm32f10x_cl.s(啟動文件) → SystemInit() → SetSysClock () → SetSysClockTo72()

        初始化時鐘用到的RCC寄存器復位值:

        RCC_CR = 0x0000 xx83; RCC_CFGR = 0x0000 0000;RCC_CIR = 0x0000 0000; RCC_CFGR2 = 0x0000 0000;

        SystemInit()

        在調用 SetSysClock()之前RCC寄存器的值如下(都是一些與運算,或運算,在此就不贅述了):

        RCC->CR = 0x0000 0083; RCC->CIR = 0x00FF0000; RCC->CFGR2 = 0x00000000;至于這些寄存器都代表著什么意思,詳見芯片資料RCC寄存器,該文重點不在此處;

        SetSysClock()函數如下:

        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 //我的定義的是SYSCLK_FREQ_72MHz,所以調用SetSysClockTo72()

         SetSysClockTo72();

        #endif

        }

        SetSysClockTo72()函數如下:

        static void SetSysClockTo72(void)

        {

         __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

         RCC->CR = ((uint32_t)RCC_CR_HSEON);

         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)

         {

         FLASH->ACR = FLASH_ACR_PRFTBE;

         FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);

         FLASH->ACR = (uint32_t)FLASH_ACR_LATENCY_2; 

         RCC->CFGR = (uint32_t)RCC_CFGR_HPRE_DIV1;

         RCC->CFGR = (uint32_t)RCC_CFGR_PPRE2_DIV1;

         RCC->CFGR = (uint32_t)RCC_CFGR_PPRE1_DIV2;

        #ifdef STM32F10X_CL

         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);

         RCC->CR = RCC_CR_PLL2ON;

         while((RCC->CR & RCC_CR_PLL2RDY) == 0)

         {

         }

         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 

         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

         RCC->CR = RCC_CR_PLLON;

         while((RCC->CR & RCC_CR_PLLRDY) == 0)

         {

         }

         RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));

         RCC->CFGR = (uint32_t)RCC_CFGR_SW_PLL; 

         while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)

         {

         }

         }

         else

         {

         }

        }

        1:AHB, APB1,APB2時鐘確定

        //HCLK = SYSCLK ,從下面的分析可以得出SYSCLK是使用PLLCLK時鐘的,也就是72MHZ(至于72MHZ如何得來,請看下面分析)

         //那么就是HCLK(AHB總線時鐘)=PLLCLK = 72MHZ 

         //AHB總線時鐘等于系統時鐘SYSCLK,也就是 AHB時鐘 = HCLK = SYSCLK = 72MHZ

         RCC->CFGR = (uint32_t)RCC_CFGR_HPRE_DIV1;

         //PLCK2等于HCLK一分頻, 所以PCLK2 = HCLK,HCLK = 72MHZ, 那么PLCK2(APB2總線時鐘) = 72MHZ 

         //APB2總線時鐘等于HCLK的一分頻,也就是不分頻;APB2 時鐘 = HCLK = SYSCLK = 72MHZ 

         RCC->CFGR = (uint32_t)RCC_CFGR_PPRE2_DIV1;

         //PCLK1 = HCLK / 2;PCLK1 等于HCLK時鐘的二分頻,那么PCLK1(APB1) = 72MHZ / 2 = 36MHZ 

         //APB1總線時鐘等于HCLK的二分頻,也就是 APB1時鐘= HCLK / 2 = 36MHZ

         RCC->CFGR = (uint32_t)RCC_CFGR_PPRE1_DIV2;

        2:如何得出SYSCLK(系統時鐘)為72MHZ(外部晶振25MHZ)

        //記得參考英文芯片資料的時鐘樹P115頁和RCC時鐘寄存器進行理解

        RCC->CFGR2 = (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 RCC_CFGR2_PLL2MUL8 RCC_CFGR2_PREDIV1SRC_PLL2 RCC_CFGR2_PREDIV1_DIV5);

        RCC_CFGR2_PREDIV2_DIV5: PREDIV2 = 5; 5分頻

         也就是PREDIV2對輸入的外部時鐘 5分頻,那么PLL2和PLL3沒有倍頻前是25 /5 = 5MHZ

        RCC_CFGR2_PLL2MUL8 : PLL2MUL = 8; 8倍頻 

         8倍頻后,PLL2時鐘 = 5 * 8 = 40MHZ; 因此 PLL2CLK = 40MHZ

        RCC_CFGR2_PREDIV1SRC_PLL2 : RCC_CFGR2的第16位為1,選擇PLL2CLK 作為PREDIV1的時鐘源

        RCC_CFGR2_PREDIV1_DIV5:PREDIV1 = 5;PREDIV1對輸入時鐘5分頻 PREDIV1CLK = PLL2CLK / 5 = 8MHZ

        以上是對RCC_CFGR2進行的配置

        --------------------------------------------------------------------------------------

        RCC->CFGR = (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 RCC_CFGR_PLLSRC_PREDIV1 

         RCC_CFGR_PLLMULL9); 

        RCC_CFGR_PLLXTPRE_PREDIV1 :操作的是RCC_CFGR的第17位PLLXTPRE,操作這一位和操作RCC_CFGR2寄存器的位[3:0]中的最低位是相同的效果 

        RCC_CFGR_PLLSRC_PREDIV1 :選擇PREDIV1輸出作為PLL輸入時鐘;PREDIV1CLK = 8MHZ,所以輸入給PLL倍頻的 時鐘源是8MHZ

        RCC_CFGR_PLLMULL9 :PLLMUL = 9;PLL倍頻系數為9,也就是對 PLLCLK = PREDIV1CLK * 8 = 72MHZ

        以上是對RCC_CFGR進行的配置

        ---------------------------------------------------------------------------------------------------

         RCC->CFGR = (uint32_t)RCC_CFGR_SW_PLL; //選擇PLLCLK作為系統時鐘源 

        --------------------------------------------------------------------------------------------------

        至此基本配置已經完成,配置的時鐘如下所述:

        SYSCLK(系統時鐘) = 72MHZ

        AHB總線時鐘 = 72MHZ

        APB1總線時鐘 = 36MHZ

        APB2總線時鐘 = 72MHZ

        PLL時鐘 = 72MHZ

        PLL2時鐘 = 40MHZ

        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮