这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » STM32时钟初始化研究

共2条 1/1 1 跳转至

STM32时钟初始化研究

高工
2018-12-20 05:45:52     打赏

时钟是一个MCU的脉搏,研究清楚脉搏才能更清楚的把握整个MCU的运行。本文主要研究STM32F10x系列,利用官方库文件进行初始化设置。开发环境为MDK4.6,库文件V3.5版本,STM32参考手册。


利用MDK自带仿真器,仿真发现。芯片启动首先打开system_stmf10x.c文件,调用void SystemInit(void)函数。下面贴上代码和中文注释


void SystemInit (void)

{

/* Reset the RCC clock configuration to the default reset state(for debug purpose) */

/* Set HSION bit */

RCC->CR |= (uint32_t)0x00000001; //内部高速时钟使能


/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */

//SW:HSI(内部高速8M RC震荡器)作为时钟源

//AHB(SYSCLK)不分频

//APB1,APB2不分频

// PCLK2 2分频后作为ADC时钟

// HSI时钟2分频后作为PLL输入时钟

//MCO没有时钟输出

RCC->CFGR &= (uint32_t)0xF8FF0000;

 

/* Reset HSEON, CSSON and PLLON bits */

//HSE振荡器关闭, 时钟安全系统监测器关闭PLL关闭

RCC->CR &= (uint32_t)0xFEF6FFFF;

 

/* Reset HSEBYP bit */

//清零来旁路外部晶体振荡器。只有在外部4-25MHz振荡器关闭的情况下,才能写入该位。

RCC->CR &= (uint32_t)0xFFFBFFFF;

 

/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */

//HSI时钟2分频后作为PLL输入时钟

//HSE不分频器作为PLL输入

//0000:PLL 2倍频输出

//0:PLL时钟1.5倍分频作为USB时钟

RCC->CFGR &= (uint32_t)0xFF80FFFF;

 

/* Disable all interrupts and clear pending bits  */

RCC->CIR = 0x009F0000;

 

/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */

/* Configure the Flash Latency cycles and enable prefetch buffer */

SetSysClock();

 

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */

}


主要是用于重置RCC寄存器,既重置STM32的时钟树。


初始化重置时钟后的时钟树图:


上文中还有个函数叫SetSysClock用于设置MCU系统时钟,贴入代码:


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

  SetSysClockTo72();

#endif

/* If none of the define above is enabled, the HSI is used as System clock source (default after reset) */

}

 

static void SetSysClockTo72(void)

{

__IO uint32_t StartUpCounter = 0, HSEStatus = 0;

 

/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/    

 

 

/* Enable HSE */    

/*define C_CR_HSEON                        (int32_t)0x00010000)   */

/*!< External High Speed clock enable */

//开启HSE振荡器

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

 


/* Wait till HSE is ready and if Time out is reached exit */

//等待HSE起振

//#define HSEStartUp_TimeOut   HSE_STARTUP_TIMEOUT

//#define HSE_STARTUP_TIMEOUT   ((uint16_t)0x0500)

/*!< Time out for HSE start up */

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

//#define  RCC_CFGR_HPRE_DIV1      ((uint32_t)0x00000000)        /*!< SYSCLK not divided */

//HCLK  :AHB总线时钟,由系统时钟SYSCLK 分频得到,不分频

RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;

 

 

/* PCLK2 = HCLK */

// #define  RCC_CFGR_PPRE2_DIV1    ((uint32_t)0x00000000)        /*!< HCLK not divided */

//APB2由AHB分频而来,不分频。

RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;

 


/* PCLK1 = HCLK */

//#define  RCC_CFGR_PPRE1_DIV2                 ((uint32_t)0x00000400)        /*!< HCLK divided by 2 */

//APB1由AHB分频而来,2分频。

RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

 

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

//设置PLLCLK时钟源为HSE,且PLL9倍频

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

 


/* Enable PLL */

//使能倍频器

RCC->CR |= RCC_CR_PLLON;

 

 

/* Wait till PLL is ready */

//等待PLL稳定运行

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

{

}


/* Select PLL as system clock source */

//设置PLL作为系统时钟源

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

//等待PLL用于系统时钟源

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

}

 

}


初始化重置时钟后的时钟树图:




管理员
2018-12-20 12:10:26     打赏
2楼

谢谢楼主分享


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]