查看: 85|回复: 0

STM32F4步步为营二:系统时钟

[复制链接]

主题

好友

5430

积分

版主

  • TA的每日心情
    擦汗
    4 天前
  • 签到天数: 731 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2014-7-18 21:48:10 |显示全部楼层
    STM32F429 Discovery开发板,集成了ST_LINK2和2.4寸的TFT  LCD彩屏,可以为学习开发带来不少的方便。此外,还有64Mbits SDRAM,ST MEMS,LED,按键及USB OTG  micro-B接口。本文将介绍STM32F4的系统时钟编程。
            系统时钟,单片机的时钟好比人们的心脏的脉波,没有脉了人就完了。同样,单片机没有系统时钟了基本上就是废片一块。
            STM32F429的时钟必须搞明白才能编程为我所用。
            以下是系统时鈡的框图:
                  
            看上去很复杂。现在一点一点的剖释。SYSCLK有三种不同的时钟可以驱动
             
    • HIS内部高速时钟       
    • HSE外部高速时钟       
    • PLL
            还有两个辅助的时钟源,分别是
             
    • LSI内部RC低速时钟32KHz主要驱动内部看门狗和RTC电路       
    • LSE外部RC低速时钟32.768主要用于驱动RTC时钟
            大部分外设都在SYSCLK下工作。除了以下一些时钟:
             
    • • USB OTG FS 时钟 (48 MHz)、random analog generator (RNG)时钟(<= 48 MHz)和SDIO时钟 (<= 48 MHz)来自PLL的输出PLL48CLK       
    • I2S clock,可以从PLL(PLLI2S)或者一个映射到I2S_CKIN管脚的外部时钟得到。       
    • SAI1 clock,可以从PLL (PLLSAI or PLLI2S)或从外部时钟映射管脚I2S_CKIN得到。PLLSAI 能被用作SAI1设备的时钟,在这种情况下PLLI2S可以被用作另外的音频(49.152 MHz or11.2896 MHz),并且两个频率同时发生。       
    • LTDC clock,LTDC时钟从PLL (PLLSAI)产生。       
    • The USB OTG HS (60 MHz) 时钟是由外部PHY提供的。       
    • The Ethernet MAC clocks (TX, RX and RMII) 时钟是由外部PHY提供的。当Ethernet被用的时候AHB时钟必须达到25MHZ
            要想平时顺利操作时钟,就必须了解几个寄存器:

            其中一个是RCC PLL配置寄存器RCC_PLLCFGR(RCC PLL configuration register),其控制着频率的生成。

             
    • • f(VCO clock) = f(PLL clock input) × (PLLN / PLLM)       
    • • f(PLL general clock output) = f(VCO clock) / PLLP       
    • • f(USB OTG FS, SDIO, RNG clock output) = f(VCO clock) / PLLQ
            大家看到上边的公式,也许会发愁,这是怎么回事,其实只要细细研究下就会非常明白:

            RCC_PLLCFGR寄存器如下:

             
    • Bits(27:24): PLLQUSB OTG FS、SDIO 和隨机数字发生器的分频值,在PLL无效时才能改写。USB OTG FS需要48 MHz 时钟才能正确工作. SDIO和隨机数字发生器需要比48MHz小或者等于48MHz时才能工作。Bits(27:24)值为2到15。       
    • Bit 22:PLLSRC,主PLL(PLL) 和音频PLL (PLLI2S) 的时钟源。当PLL和PLLI2S没使能的情况下可改写,0为内部高速时钟被选择;1为外部晶振时钟被选择。       
    • Bits(17:16):PLLP,主PLL (PLL) 分频为系统时钟的分频值。当PLL没有使能时改写。注意该值不应超过180MHz,PLL 输出时钟 = VCO 频率 / PLLP (PLLP = 2, 4, 6, or 8)。       
    • Bits(14:6):PLLN,主PLL (PLL)乘积因子,VCO的乘积因子,可以软件清除和设置。这个只有两种选项192MHzt和432MHz,输入频率最小为1MHzVCO output frequency = VCO input frequency × PLLN with 192 MHz或432MHz。       
    • Bits(5:0):PLLM,主 PLL (PLL) 和音频PLL (PLLI2S) 输入时钟的分频因子,这个是保证在输入VCO的频率在1到2MHz之间,它的值为2到63。VCO input frequency = PLL input clock frequency / PLLM with (2-63)
            另一个寄存器是:RCC时钟控制 寄存器RCC_CR(RCC clock control register )
             
    • Bit29:PLLSAIRDY,PLLSAI 时钟锁定标志       
    • Bit28:PLLISAION,PLLSAI有效       
    • Bit27:PLLI2SRDY,PLLI2S准备好标志       
    • Bit26:PLLI2SON,PLLI2S 有效       
    • Bit25:PLLRDY,主PLL (PLL) clock 准备好标志       
    • Bit24:PLLON,主PLL (PLL)使能
            还有一个寄存器是:RCC时钟配置寄存器RCC_CFGR(RCC clock configuration register)

            里边有APB1,APB2,AHB 各个总线的分频因子。

            由此,我们不难读懂如下函数:

            static void SetSysClock(void)    {    /******************************************************************************    * PLL (clocked by HSE) used as System clock source *    ******************************************************************************/    __IO uint32_t StartUpCounter = 0, HSEStatus = 0;    #ifdef PLL_SOURCE_HSI //如果时钟源定义为内部低速时钟           RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |(RCC_PLLCFGR_PLLSRC_HSI) | (PLL_Q << 24);    #else           RCC->CR |= ((uint32_t)RCC_CR_HSEON); //定义时钟源为内部高速时钟    #ifdef PLL_SOURCE_HSE_BYPASS //如果定义外部时钟为 BYPASS模式           RCC->CR |= ((uint32_t)RCC_CR_HSEBYP);    #endif         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)      {        //如果外部时钟稳定就开始配置主时钟        RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |                      (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);      }        else      {        //否则就表示外部时钟出了问题,用户可以自己加些代码处理这个问题      }    #endif        //设置系统频率为180MHZ    RCC->APB1ENR |= RCC_APB1ENR_PWREN;        PWR->CR |= PWR_CR_VOS;    //设置HCLK频率    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;        //设置PCLK2 = HCLK / 2        RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;         //设置PCLK1 = HCLK / 4        RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;        //使能PLL        RCC->CR |= RCC_CR_PLLON;       //等待PLL准备好        while((RCC->CR & RCC_CR_PLLRDY) == 0)        {        }        //设置扩展时钟为180MHZ        PWR->CR |= PWR_CR_ODEN;        while((PWR->CSR & PWR_CSR_ODRDY) == 0)        {        }        PWR->CR |= PWR_CR_ODSWEN;        while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)        {        }         //设置FLASH,预取指令缓冲和数据缓冲和等待状态         FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;        //选取主PLL时钟为系统时钟源         RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));        RCC->CFGR |= RCC_CFGR_SW_PLL;    //等待时钟稳定        while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);        {        }    }       
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    关闭

    站长推荐上一条 /4 下一条

    手机版|电路城

    GMT+8, 2019-7-20 01:35 , Processed in 0.147735 second(s), 14 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz!

    返回顶部