• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > STM32時(shí)鐘初始化函數(shù)SystemInit()詳解

    STM32時(shí)鐘初始化函數(shù)SystemInit()詳解

    作者: 時(shí)間:2016-09-28 來(lái)源:網(wǎng)絡(luò) 收藏

      花了一天的時(shí)間,總算是了解了SystemInit()函數(shù)實(shí)現(xiàn)了哪些功能,初學(xué),,現(xiàn)記錄如下(有理解錯(cuò)誤的地方還請(qǐng)大俠指出):

    本文引用地址:http://www.czjhyjcfj.com/article/201609/310557.htm

      使用的是3.5的庫(kù),用的是F107VC,開發(fā)環(huán)境RVMDK4.23

      我已經(jīng)定義了F10X_CL,SYSCLK_FREQ_72MHz

      函數(shù)調(diào)用順序:

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

      初始化用到的RCC寄存器復(fù)位值:

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

      SystemInit()

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

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

      SetSysClock()函數(shù)如下:

      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,所以調(diào)用SetSysClockTo72()

      SetSysClockTo72();

      #endif

      }

      SetSysClockTo72()函數(shù)如下:

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

      /* 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)

      {

      /* 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;

      /* PCLK2 = HCLK */

      RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;

      /* PCLK1 = HCLK */

      RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

      #ifdef STM32F10X_CL

      /* Configure PLLs ------------------------------------------------------*/

      /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */

      /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */

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

      /* Enable PLL2 */

      RCC->CR |= RCC_CR_PLL2ON;

      /* Wait till PLL2 is ready */

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

      {

      }

      /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */

      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

      /* 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 */

      /* 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 */

      }

      }

      1:AHB, APB1,APB2確定

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

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

      //AHB總線時(shí)鐘等于系統(tǒng)時(shí)鐘SYSCLK,也就是 AHB時(shí)鐘 = HCLK = SYSCLK = 72MHZ

      /* HCLK = SYSCLK */

      RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;

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

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

      /* PCLK2 = HCLK */

      RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;

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

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

      /* PCLK1 = HCLK */

      RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

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

      //記得參考英文芯片資料的時(shí)鐘樹P115頁(yè)和RCC時(shí)鐘寄存器進(jìn)行理解

      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對(duì)輸入的外部時(shí)鐘 5分頻,那么PLL2和PLL3沒有倍頻前是25 /5 = 5MHZ

      RCC_CFGR2_PLL2MUL8 : PLL2MUL = 8; 8倍頻

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

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

      RCC_CFGR2_PREDIV1_DIV5:PREDIV1 = 5;PREDIV1對(duì)輸入時(shí)鐘5分頻 PREDIV1CLK = PLL2CLK / 5 = 8MHZ

    以上是對(duì)RCC_CFGR2進(jìn)行的配置

     

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

      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輸入時(shí)鐘;PREDIV1CLK = 8MHZ,所以輸入給PLL倍頻的 時(shí)鐘源是8MHZ

      RCC_CFGR_PLLMULL9 :PLLMUL = 9;PLL倍頻系數(shù)為9,也就是對(duì) PLLCLK = PREDIV1CLK * 8 = 72MHZ

      以上是對(duì)RCC_CFGR進(jìn)行的配置

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

      RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL; //選擇PLLCLK作為系統(tǒng)時(shí)鐘源

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

      至此基本配置已經(jīng)完成,配置的時(shí)鐘如下所述:

      SYSCLK(系統(tǒng)時(shí)鐘) = 72MHZ

      AHB總線時(shí)鐘 = 72MHZ

      APB1總線時(shí)鐘 = 36MHZ

      APB2總線時(shí)鐘 = 72MHZ

      PLL時(shí)鐘 = 72MHZ

      PLL2時(shí)鐘 = 40MHZ



    關(guān)鍵詞: STM32 時(shí)鐘

    評(píng)論


    相關(guān)推薦

    技術(shù)專區(qū)

    關(guān)閉
    主站蜘蛛池模板: 灵川县| 波密县| 西安市| 德惠市| 隆安县| 巨野县| 利津县| 仁布县| 峨山| 宝山区| 防城港市| 洛阳市| 民乐县| 遂宁市| 潼关县| 长沙市| 清镇市| 简阳市| 津南区| 康马县| 德清县| 盘山县| 九龙县| 永平县| 宁南县| 贡嘎县| 潼关县| 佛教| 定州市| 潜山县| 淮南市| 隆林| 郁南县| 黄山市| 惠来县| 泰顺县| 昭觉县| 昭苏县| 巴楚县| 五台县| 贺兰县|