lxj19901115的个人空间 https://bbs.21ic.com/?754113 [收藏] [复制] [RSS]

日志

关于STM32F0内部时钟配置到48M

已有 3227 次阅读2015-4-8 11:22 |个人分类:备份|系统分类:单片机

先上代码
  __IO uint32_t StartUpCounter = 0, HSIStatus = 0;
        RCC->CR |=((uint32_t)RCC_CR_HSION);
        do
        {
                        HSIStatus = RCC->CR & RCC_CR_HSIRDY;
                        StartUpCounter++;               
        }while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT));
        if(RCC->CR & RCC_CR_HSIRDY)
        {
                        HSIStatus = 0x01;
        }
        else
        {
                        HSIStatus = 0x00;
        }
        if(HSIStatus == 0x01)
        {
    /* Enable Prefetch Buffer and set Flash Latency */
    FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
 
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;

    /* PLL configuration = HSI * 6 = 48 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_PREDIV | RCC_CFGR_PLLMULL6);
            
    /* Enable PLL */
    RCC->CR |= RCC_CR_PLLON;

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

    /* Select PLL as system clock source */
    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 */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
    {
    }
                 
        }

接着来说明下,
很多人拿到官方的例程代码里面的时钟配置是基于使用外部晶振的,但是为了节省成本,所以很多人都选择使用内部RC,
下面是内部RC的配置流程,
首先配置
        RCC->CR |=((uint32_t)RCC_CR_HSION);
开启内部时钟,
在开启内部时钟之后,那么要等待内部时钟就绪,
        do
        {
                        HSIStatus = RCC->CR & RCC_CR_HSIRDY;
                        StartUpCounter++;               
        }while((HSIStatus == 0) && (StartUpCounter != HSI_STARTUP_TIMEOUT));
        if(RCC->CR & RCC_CR_HSIRDY)
        {
                        HSIStatus = 0x01;
        }
        else
        {
                        HSIStatus = 0x00;
        }
并设置好状态,
    /* Enable Prefetch Buffer and set Flash Latency */
    FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
 
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
      
    /* PCLK = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;
这一部分的代码是和外部晶振的代码配置一样的,
   RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_PREDIV | RCC_CFGR_PLLMULL6);
关键代码是这一句,
而配置外部时钟的时候
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL6);
语句是这样的,很多人都以为,
只要修改为内部时钟即可,但是很多的代码都是在PLL开启的时候限入死循环,

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
死在这里,
死在这里的原因是什么呢,
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL6);
的解释如下,,,RCC_CFGR_PLLXTPRE_PREDIV1
这一句说的是,PLLCLK INPUT的来源外部晶振,所以,这里不对,
那么要使用内部晶振的配置
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSI_PREDIV | RCC_CFGR_PLLMULL6);
是这样的,这样的配置是,PLL的来源是来自内部晶振,而且这个来源的时钟不是通过2分频的,所以直接是通过8M来倍频的,
所以6X8是等于48M的,


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)