对于小型化的设备,特别是对时钟要求不高且出货量大的产品,每一颗物料都要精打细算,省下来的都是成本。如果不要晶振,每个产品都能省下一颗晶振和两颗电容,量变引起质变,嗯~还是有必要的。
此次勒裤腰带的是STM32F0,现在晶振可不便宜(好像一直都不便宜),而且日本厂商还宣布电容涨价。能省就省吧。而且经过测试,STM32的内部晶振还是很可靠的,如果不使用精准的计时,这个晶振真的可以摘。
- static void SetSysClock(void)
- {
- __IO uint32_t StartUpCounter = 0, HSIStatus = 0;
- RCC->CR &= ~((uint32_t)RCC_CR_HSEON); //关闭外部时钟
- RCC->CR |= ((uint32_t)RCC_CR_HSION); //使能内部时钟 HSI
- do //等待内部时钟起振
- {
- HSIStatus = RCC->CR & RCC_CR_HSIRDY; // 设置RCC
- StartUpCounter++; //启动计数器
- }
- while((HSIStatus== 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT)); // 等待 HSE 启动稳定
- if ((RCC->CR & RCC_CR_HSIRDY) != RESET) //判断启动状态
- {
- HSIStatus = (uint32_t)0x01;
- }
- else
- {
- HSIStatus = (uint32_t)0x00; //启动不成功
- }
- if (HSIStatus == (uint32_t)0x01) //启动成功
- {
- /* Enable Prefetch Buffer and set Flash Latency */
- FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY; //flash总线时钟使能
- /* HCLK = SYSCLK */ //AHB总线时钟HCLK(是系统时钟SYSCLK经过AHB分频器分频后得到的时钟,
- //一般设置1分频,HCLK=SYSSCLK=48MHz;
- RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1; //AHB总线时钟 HCLK = SYSCLK/1=48MHz
- /* PCLK = HCLK */ //APB总线时钟PCLK等于AHB总线时钟/1 PCLK=HCLK/1
- RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1; // PCLK=HCLK/1=48M/1=48M
- /* PLL configuration = HSI/2 * 12= 48 MHz */
- RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL));
- RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_Div2 | RCC_CFGR_PLLMULL14);
- //RC时钟2分频后 进行12倍频
- //=8M/2*12=48M
- RCC->CR |= RCC_CR_PLLON; //使能锁相环倍频开关 /* Enable PLL */
- while((RCC->CR & RCC_CR_PLLRDY) == 0) //等待锁相环就绪
- { }
- //选择锁相环输出时钟作为系统时钟
- RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
- RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
- while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
- { } //等待锁相环输出时钟已经成为系统时钟
- }
- else
- { } //启动失败,在此写代码
- }
修改时钟配置在system_stm32f0xx.c文件中进行。主要修改SetSysClock(void)这个函数,该函数默认使用外部晶振,上电会尝试启动外部时钟,通过while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL) 来判断是否启动成功,如果启动失败则会进入else尝试启动内部时钟,但是官方的库else里面是空的,我们则需要填充这部分内容。
|