stm32f10x 标准外设固件库时钟配置函数分析
来源:互联网 发布:c语言在线编程 编辑:程序博客网 时间:2024/04/29 01:41
为了使stm32f10x的初学者在学习STM32的时候不必去考虑STM32f10x复杂的时钟系统,官方提供了时钟配置的函数并在调用main函数之前调用,这在启动文件中可以看到,以STM32F103VC为例(以后芯片均已此款芯片为例),对应的启动文件为startup_stm32f10x_hd.s
; Reset handlerReset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main IMPORT SystemInit LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP
下面来看看 SystemInit 函数中到底做了哪些事
void SystemInit (void){ RCC->CR |= (uint32_t)0x00000001;//开启内部8MHz振荡器#ifndef STM32F10X_CL//非STM32F10x互联型 RCC->CFGR &= (uint32_t)0xF8FF0000;//HSI作为系统时钟 AHB预分频器不分频 APB1不分频 APB2不分频 PCLK 2分频后作为ADC时钟 MCO无时钟输出#else//STM32F10x互联型 RCC->CFGR &= (uint32_t)0xF0FF0000;//HSI作为系统时钟 AHB预分频器不分频 APB1不分频 APB2不分频 PCLK 2分频后作为ADC时钟 MCO无时钟输出#endif /* STM32F10X_CL */ RCC->CR &= (uint32_t)0xFEF6FFFF;//HSE 振荡器关闭 时钟监测器关闭 PLL关闭 RCC->CR &= (uint32_t)0xFFFBFFFF;//外部4-16Mhz 振荡器没有旁路 RCC->CFGR &= (uint32_t)0xFF80FFFF;//HSI振荡器时钟经2分频后作为PLL输入时钟 HSE不分频 PLL 2倍频输出 PLL 时钟1.5分频作为USB时钟#ifdef STM32F10X_CL//STM32F10x互联型 RCC->CR &= (uint32_t)0xEBFFFFFF;//PLL2 关闭 PLL3 关闭 RCC->CIR = 0x00FF0000;//关闭所有中断并清除所有中断标志位 RCC->CFGR2 = 0x00000000;//复位CFGR2寄存器#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) //STM32F10X 超值产品线 RCC->CIR = 0x009F0000;//关闭所有中断并清除所有中断标志位 RCC->CFGR2 = 0x00000000;//复位CFGR2寄存器#else RCC->CIR = 0x009F0000;//关闭所有中断并清除所有中断标志位#endif /* STM32F10X_CL */ #if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)//这段代码用于STM3210E-EVAL 板使用外部SRAM #ifdef DATA_IN_ExtSRAM SystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM */#endif SetSysClock();//配置系统时钟 HCLK PCLK1 PCLK2 预分频器 FLASH 延时周期和预取缓冲器#ifdef VECT_TAB_SRAM SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;//内部SRAM向量表迁移#else SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; //内部FLASH向量表迁移#endif }
下面看看 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 SetSysClockTo72();#endif}
根据不同的宏定义来调用不同的函数 如果上述的宏定义都没有定义 则HSI作为系统时钟(复位后的默认情况)
我这里以SetSysClockTo72 函数为例分析
static void SetSysClockTo72(void){ __IO uint32_t StartUpCounter = 0, HSEStatus = 0; RCC->CR |= ((uint32_t)RCC_CR_HSEON);//开启HSE振荡器 /* 等待HSE就绪如果超时则退出 */ do { HSEStatus = RCC->CR & RCC_CR_HSERDY;//获取HSE就绪标志位 StartUpCounter++; } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT)); if ((RCC->CR & RCC_CR_HSERDY) != RESET)//如果HSE就绪 { HSEStatus = (uint32_t)0x01; } else { HSEStatus = (uint32_t)0x00; } if (HSEStatus == (uint32_t)0x01)//如果HSE就绪 { FLASH->ACR |= FLASH_ACR_PRFTBE;//使能 FLASH 预取缓冲区 FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY); FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2; //FLASH 2 等待状态(48 MHz < SYSCLK ≤ 72 MHz ) RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;//HCLK = SYSCLK RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;//PCLK2 = HCLK RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;//PCLK1 = HCLK/2 #ifdef STM32F10X_CL RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);// PLL2CLK = (HSE / 5) * 8 = (25M / 5) * 8 = 40 MHz PREDIV1CLK = PLL2 / 5 = 8 MHz RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5); RCC->CR |= RCC_CR_PLL2ON;//使能PLL2 while((RCC->CR & RCC_CR_PLL2RDY) == 0)//等待 PLL2 就绪 { } /* PLL 配置: 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 配置: 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 */ RCC->CR |= RCC_CR_PLLON;//使能PLL while((RCC->CR & RCC_CR_PLLRDY) == 0)//等待PLL就绪 { } RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;//选择PLL作为系统时钟 while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)//等待PLL作为系统时钟就绪 { } } else { //如果 HSE 启动失败,系统得到错误的时钟,用户添加代码解决这个错误 }}至此,系统时钟配置完成,在使用STM外设打开相应的时钟开关就可以操作对应外设。
0 0
- stm32f10x 标准外设固件库时钟配置函数分析
- STM32F10x时钟相关分析
- STM32标准外设库学习笔记-20150823-阅读stm32f10x.h
- STM32F10X 时钟相关代码及分析
- stm32f4xx标准外设固件库
- STM32 Tips:如何从ST官方网站上下载STM32标准外设库(STM32F10x standard peripheral library)
- STM32F10x芯片RTC实时时钟
- STM32F10X时钟系统学习笔记
- STM32F10X的时钟树及时钟初始化
- STM32标准外设库
- STM32F10x 启动代码分析
- 详细分析stm32f10x.h
- 详细分析stm32f10x.h
- STM32F10X的boot分析
- 详细分析stm32f10x.h
- STM32 外设操作时钟注意事项
- stm32f4 - 时钟树分析配置
- 设置外设时钟使能时钟
- 试手破解soapUI and readyAPI
- kafka的producer测试
- AIDL调用第三方应用程序服务中的方法
- 复习C++
- stl中set和hash_set底层实现详解
- stm32f10x 标准外设固件库时钟配置函数分析
- UGUI学习笔记3——UI组件
- 第0章 操作系统概念
- socket 、webservices、Json的区别
- hadoop自定义序列化
- 新装LINUX系统如何获得ROOT权限,图文教程
- 一起talk C栗子吧(第五十回:C语言实例--最小生成树二)
- 万能适配器2 通用Adapter编写
- Dagger的简单介绍