您的位置 首页 技术

STM32时钟初始化函数SystemInit()详解

花了一天的时间,总算是了解了SystemInit()函数实现了哪些功能,初学STM32,,现记录如下(有理解错误的地方还请大侠指出):使用的是3.5的库,用的是STM32F107VC,开发

  花了一天的时刻,总算是了解了SystemInit()函数完结了哪些功用,初学STM32,,现记载如下(有了解过错的当地还请大侠指出):

  运用的是3.5的库,用的是STM32F107VC,开发环境RVMDK4.23

  我现已界说了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;

  /* 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怎么得来,请看下面剖析)

  //那么便是HCLK(AHB总线时钟)=PLLCLK = 72MHZ

  //AHB总线时钟等于体系时钟SYSCLK,也便是 AHB时钟 = HCLK = SYSCLK = 72MHZ

  /* HCLK = SYSCLK */

  RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;

  //PLCK2等于HCLK一分频, 所以PCLK2 = HCLK,HCLK = 72MHZ, 那么PLCK2(APB2总线时钟) = 72MHZ

  //APB2总线时钟等于HCLK的一分频,也便是不分频;APB2 时钟 = HCLK = SYSCLK = 72MHZ

  /* PCLK2 = HCLK */

  RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;

  //PCLK1 = HCLK / 2;PCLK1 等于HCLK时钟的二分频,那么PCLK1(APB1) = 72MHZ / 2 = 36MHZ

  //APB1总线时钟等于HCLK的二分频,也便是 APB1时钟= HCLK / 2 = 36MHZ

  /* PCLK1 = HCLK */

  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

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/jishu/298641.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部