STM32F407的时钟配置(system_config.c浅见)
2013-12-14 13:23
447 查看
入手STM32F4系列是从F4Discovery开始的,板子确实很对得起99元的价格~因为最近要做一个图像识别方面的项目,因此开始在f4上进行编程,之前也写过f103系类的单片机,但时钟方面都是使用别人已经写好的时钟配置函数,没有去仔细考虑,换用了f4之后,分析了一下系统的启动过程,发现system_config.c中的SystemInit函数已经把时钟配置好了,但还有一些地方需要做修改,否则可能会导致时钟启动过程出现错误,现在 写出来,也算是做的个备忘吧。
startup_stm32f40_41xxx.s是怎么对SystemInit进行调用的呢?见103行:
因此跳到SystemInit一探究竟:
可见,该函数打开了HSE,PLL(当然还有一些其他功能,如浮点运算,这里不作讨论),并且在最后引用了setsysclock()
系统时钟具体可以参考以下公式:
PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N;
SYSCLK = PLL_VCO / PLL_P;
USB时钟,SDIO可以参考:
USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLL_Q;
比如使用8M的外部晶振,那么PLL_M=8, PLL_N=336, PLL_P=2 就可以配置出168M的系统时钟了。如果PLL_Q=7, USB, SDIO时钟为48M。
另外,还需注意的一点时,PCLK1,也就是APB1时钟不能大于42M,PCLK2不能大于84M,USB,SDIO时钟不能大于48M。
这样,就可以不用使用自己编写的时钟配置函数了~
startup_stm32f40_41xxx.s是怎么对SystemInit进行调用的呢?见103行:
/* Call the clock system intitialization function.*/ bl SystemInit
因此跳到SystemInit一探究竟:
void SystemInit(void) { /* FPU settings ------------------------------------------------------------*/ #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ #endif /* Reset the RCC clock configuration to the default reset state ------------*/ /* Set HSION bit */ RCC->CR |= (uint32_t)0x00000001; /* Reset CFGR register */ RCC->CFGR = 0x00000000; /* Reset HSEON, CSSON and PLLON bits */ RCC->CR &= (uint32_t)0xFEF6FFFF; /* Reset PLLCFGR register */ RCC->PLLCFGR = 0x24003010; /* Reset HSEBYP bit */ RCC->CR &= (uint32_t)0xFFFBFFFF; /* Disable all interrupts */ RCC->CIR = 0x00000000; #if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) SystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ /* Configure the System clock source, PLL Multiplier and Divider factors, AHB/APBx prescalers and Flash settings ----------------------------------*/ SetSysClock(); /* Configure the Vector Table location add offset address ------------------*/ #ifdef VECT_TAB_SRAM SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ #else SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ #endif }
可见,该函数打开了HSE,PLL(当然还有一些其他功能,如浮点运算,这里不作讨论),并且在最后引用了setsysclock()
static void SetSysClock(void) { /******************************************************************************/ /* PLL (clocked by HSE) used as System clock source */ /******************************************************************************/ __IO uint32_t StartUpCounter = 0, HSEStatus = 0; /* 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) { /* Select regulator voltage output Scale 1 mode */ RCC->APB1ENR |= RCC_APB1ENR_PWREN; PWR->CR |= PWR_CR_VOS; /* HCLK = SYSCLK / 1*/ RCC->CFGR |= RCC_CFGR_HPRE_DIV1; #if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx) /* PCLK2 = HCLK / 1*/ RCC->CFGR |= RCC_CFGR_PPRE2_DIV2; /* PCLK1 = HCLK / 1*/ RCC->CFGR |= RCC_CFGR_PPRE1_DIV4; #endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx */ #if defined (STM32F401xx) /* PCLK2 = HCLK / 2*/ RCC->CFGR |= RCC_CFGR_PPRE2_DIV1; /* PCLK1 = HCLK / 4*/ RCC->CFGR |= RCC_CFGR_PPRE1_DIV2; #endif /* STM32F401xx */ /* Configure the main PLL */ RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) | (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24); /* Enable the main PLL */ RCC->CR |= RCC_CR_PLLON; /* Wait till the main PLL is ready */ while((RCC->CR & RCC_CR_PLLRDY) == 0) { } #if defined (STM32F427_437xx) || defined (STM32F429_439xx) /* Enable the Over-drive to extend the clock frequency to 180 Mhz */ PWR->CR |= PWR_CR_ODEN; while((PWR->CSR & PWR_CSR_ODRDY) == 0) { } PWR->CR |= PWR_CR_ODSWEN; while((PWR->CSR & PWR_CSR_ODSWRDY) == 0) { } /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; #endif /* STM32F427_437x || STM32F429_439xx */ #if defined (STM32F40_41xxx) /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS; #endif /* STM32F40_41xxx */ #if defined (STM32F401xx) /* Configure Flash prefetch, Instruction cache, Data cache and wait state */ FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_2WS; #endif /* STM32F401xx */ /* Select the main PLL as system clock source */ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW)); RCC->CFGR |= RCC_CFGR_SW_PLL; /* Wait till the main PLL is used as system clock source */ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL); { } } 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 */ } }看出,该函数定义了PLL倍频系数,AHB,APB1,APB2时钟(也就是HCLK,PCLK1,PCLK2),根据不同的器件的定义,分别设置了不同的是,时钟频率,可以改变PLL_N,PLL_M,PLL_P,PLL_Q的值,和RCC_CFGR_PPRE2_DIVx,RCC_CFGR_PPRE1_DIVx就可以改变了,x代表分频系数。
系统时钟具体可以参考以下公式:
PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N;
SYSCLK = PLL_VCO / PLL_P;
USB时钟,SDIO可以参考:
USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLL_Q;
比如使用8M的外部晶振,那么PLL_M=8, PLL_N=336, PLL_P=2 就可以配置出168M的系统时钟了。如果PLL_Q=7, USB, SDIO时钟为48M。
另外,还需注意的一点时,PCLK1,也就是APB1时钟不能大于42M,PCLK2不能大于84M,USB,SDIO时钟不能大于48M。
这样,就可以不用使用自己编写的时钟配置函数了~
相关文章推荐
- Keil STM32工程环境搭建
- stm32之RTC
- STM32串口操作相关事项
- stm32的1602操作显示
- STM32 IAP
- 红龙103开发板CAN IAP
- STM32开发板点灯
- 第一个博客
- 普通I/O口的追根溯源 (1)
- STM32 系统架构及存储器映射
- STM32系统架构和存储器映射
- STM32学习顺序
- stm32库函数void SystemInit (void)分析
- stm32库函数GPIO_PinRemapConfig分析
- STM32菜鸟之初始化函数以及延时函数
- STM32之端口复用与重映射简单说明
- Programming STM32 F2, F4 ARMs under Linux: A Tutorial from Scratch
- V3.5库函数下SysTick的学习使用
- CC2500调试心得
- STM32延时us程序