搜索

[STM32] STM32F0使用内部晶振并超频

[复制链接]
68|1
 楼主 | 2021-3-19 15:19 | 显示全部楼层 |阅读模式
对于小型化的设备,特别是对时钟要求不高且出货量大的产品,每一颗物料都要精打细算,省下来的都是成本。如果不要晶振,每个产品都能省下一颗晶振和两颗电容,量变引起质变,嗯~还是有必要的。
此次勒裤腰带的是STM32F0,现在晶振可不便宜(好像一直都不便宜),而且日本厂商还宣布电容涨价。能省就省吧。而且经过测试,STM32的内部晶振还是很可靠的,如果不使用精准的计时,这个晶振真的可以摘。

  1. static void SetSysClock(void)
  2. {
  3.          __IO uint32_t StartUpCounter = 0, HSIStatus = 0;

  4.         RCC->CR &= ~((uint32_t)RCC_CR_HSEON);                                     //关闭外部时钟
  5.          RCC->CR |= ((uint32_t)RCC_CR_HSION);                                                  //使能内部时钟 HSI
  6.        do                                                                                                                    //等待内部时钟起振
  7.            {
  8.             HSIStatus = RCC->CR & RCC_CR_HSIRDY;                                              // 设置RCC
  9.             StartUpCounter++;                                                                                         //启动计数器
  10.             }
  11.        while((HSIStatus== 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT));  // 等待 HSE 启动稳定

  12.        if ((RCC->CR & RCC_CR_HSIRDY) != RESET)                                             //判断启动状态
  13.            {
  14.             HSIStatus = (uint32_t)0x01;
  15.            }
  16.        else
  17.            {
  18.              HSIStatus = (uint32_t)0x00;                                                                       //启动不成功
  19.             }

  20.        if (HSIStatus == (uint32_t)0x01) //启动成功
  21.            {
  22.             /* Enable Prefetch Buffer and set Flash Latency */
  23.            FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;      //flash总线时钟使能

  24.            /* HCLK = SYSCLK */      //AHB总线时钟HCLK(是系统时钟SYSCLK经过AHB分频器分频后得到的时钟,

  25.                                                    //一般设置1分频,HCLK=SYSSCLK=48MHz;

  26.            RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;    //AHB总线时钟  HCLK = SYSCLK/1=48MHz

  27.            /* PCLK = HCLK */         //APB总线时钟PCLK等于AHB总线时钟/1   PCLK=HCLK/1
  28.            RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;                    // PCLK=HCLK/1=48M/1=48M

  29.            /* PLL configuration = HSI/2 * 12= 48 MHz */
  30.            RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL));
  31.            RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_Div2 | RCC_CFGR_PLLMULL14);   

  32.                                                                                                                     //RC时钟2分频后 进行12倍频
  33.                                                                                                                     //=8M/2*12=48M
  34.            RCC->CR |= RCC_CR_PLLON;                                                      //使能锁相环倍频开关 /* Enable PLL */

  35.            while((RCC->CR & RCC_CR_PLLRDY) == 0)                                //等待锁相环就绪
  36.                    { }

  37.                                                   //选择锁相环输出时钟作为系统时钟
  38.            RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
  39.            RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;

  40.            while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
  41.                     { }                                                                                          //等待锁相环输出时钟已经成为系统时钟
  42.             }
  43.          else
  44.                { }                                                                                              //启动失败,在此写代码
  45.        }
复制代码
修改时钟配置在system_stm32f0xx.c文件中进行。主要修改SetSysClock(void)这个函数,该函数默认使用外部晶振,上电会尝试启动外部时钟,通过while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL) 来判断是否启动成功,如果启动失败则会进入else尝试启动内部时钟,但是官方的库else里面是空的,我们则需要填充这部分内容。
  1. /* If HSE fails to start-up, the application will have wrong clock
  2.          configuration. User can add here some code to deal with this error */
  3.                    // HSI 内部时钟做为PLL时钟源并配置PLL 56M做为系统时钟
  4.     /* Enable Prefetch Buffer and set Flash Latency */
  5.     FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;

  6.     /* HCLK = SYSCLK */
  7.     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;

  8.     /* PCLK = HCLK */
  9.     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;

  10.     // PLL configuration = (HSI/2) * 12 = 48 MHz
  11.     RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_14); // 8M/2 * 14 = 56M

  12.     /* Enable PLL */
  13.     RCC->CR |= RCC_CR_PLLON;

  14.     /* Wait till PLL is ready */
  15.     while ((RCC->CR & RCC_CR_PLLRDY) == 0)
  16.     {
  17.     }

  18.     /* Select PLL as system clock source */
  19.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // PLL 做系统时钟

  20.     /* Wait till PLL is used as system clock source */
  21.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
  22.     {
  23.     }
复制代码
将上述内容填充进else便可,只需修改RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_14);中的RCC_PLLMul_14参数便可修改主频。
为了切换内外部时钟方便,可在函数开头加
121176054500ba50b9.png
屏蔽上面一行则使用内部时钟,屏蔽下面一行则使用外部时钟。
我贴的代码是使用内部时钟并超频到56M,标准是48M。
下面贴上所有代码:
  1. static void SetSysClock(void)
  2. {
  3.   __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  4.   
  5.   /* SYSCLK, HCLK, PCLK configuration ----------------------------------------*/
  6.   /* Enable HSE */   
  7. //修改为内部晶振       
  8. //RCC->CR |= ((uint32_t)RCC_CR_HSEON);
  9.         RCC->CR &= ~((uint32_t)RCC_CR_HSEON);

  10.   /* Wait till HSE is ready and if Time out is reached exit */
  11.   do
  12.   {
  13.     HSEStatus = RCC->CR & RCC_CR_HSERDY;
  14.     StartUpCounter++;  
  15.   } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  16.   if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  17.   {
  18.     HSEStatus = (uint32_t)0x01;
  19.   }
  20.   else
  21.   {
  22.     HSEStatus = (uint32_t)0x00;
  23.   }  

  24.   if (HSEStatus == (uint32_t)0x01)
  25.   {
  26.     /* Enable Prefetch Buffer and set Flash Latency */
  27.     FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;

  28.     /* HCLK = SYSCLK */
  29.     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
  30.       
  31.     /* PCLK = HCLK */
  32.     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;

  33.     /* PLL configuration = HSE * 6 = 48 MHz */
  34.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
  35.     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL7);
  36.             
  37.     /* Enable PLL */
  38.     RCC->CR |= RCC_CR_PLLON;

  39.     /* Wait till PLL is ready */
  40.     while((RCC->CR & RCC_CR_PLLRDY) == 0)
  41.     {
  42.     }

  43.     /* Select PLL as system clock source */
  44.     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
  45.     RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;   

  46.     /* Wait till PLL is used as system clock source */
  47.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
  48.     {
  49.     }
  50.   }
  51.   else
  52.   { /* If HSE fails to start-up, the application will have wrong clock
  53.          configuration. User can add here some code to deal with this error */
  54.                    // HSI 内部时钟做为PLL时钟源并配置PLL 56M做为系统时钟
  55.     /* Enable Prefetch Buffer and set Flash Latency */
  56.     FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;

  57.     /* HCLK = SYSCLK */
  58.     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;

  59.     /* PCLK = HCLK */
  60.     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;

  61.     // PLL configuration = (HSI/2) * 12 = 48 MHz
  62.     RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_14); // 8M/2 * 14 = 56M

  63.     /* Enable PLL */
  64.     RCC->CR |= RCC_CR_PLLON;

  65.     /* Wait till PLL is ready */
  66.     while ((RCC->CR & RCC_CR_PLLRDY) == 0)
  67.     {
  68.     }

  69.     /* Select PLL as system clock source */
  70.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // PLL 做系统时钟

  71.     /* Wait till PLL is used as system clock source */
  72.     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
  73.     {
  74.     }
  75.   }  
  76. }
复制代码


使用特权

评论回复
| 2021-3-19 17:38 | 显示全部楼层
谢谢楼主分享,

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 我要提问 投诉建议 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表