zoukankan      html  css  js  c++  java
  • Cotex-M3内核LPC17xx系列时钟及其配置方法

    一、背景:

      最近正在接手一个项目,核心芯片既是LPC17XX系列MCU,内核为ARM的Cotex-M3内核。

      想要玩转一个MCU,就一定得搞定其时钟!

      时钟对MCU而言,就好比人类的心脏。由其给AHB、APB总线供给血液(时钟频率),而挂在AHB(Advance High Bus)总线上的器件就像是我们的各个器官,挂在APB(Adance Peripheral Bus)总线的外设就像是人类的四肢。各个器官和四肢只有在你的血液(时钟频率)供给恰到好处时才能正常运转。

      本篇文章既是对LPC17xx系列的时钟结构及其配置方法做个介绍与总结。

    二、正文:

      二话不说,先上一张LPC17xx时钟。

     

      由图所示,MCU最原始的时钟动力来自于上图三个地方之一,

        osc_clk-->由外接在”XTAL1”,”XTAL2”的晶振来提供时钟源;

        rtc_clk-->由外接在”RTCX1”,”RTCX2”的晶振来提供时钟源;

        irc_osc-->由MCU内部自带的晶振来提供时钟源。

      又由图知,LPC1700系列一共有4大类时钟,

      供给CPU直接使用的CCLK时钟;

      供给USB使用的usb_clk时钟;

      供给看门狗使用的wd_clk时钟;

      供给各种外设使用的pclk时钟;

      CCLK时钟由主PLL(PLL0)或者直接由三个晶振源之一来提供;

      usb_clk时钟由主PLL(PLL0)或者PLL1提供;

      pclk时钟由CCLK分频得来;

      wd_clk时钟由”rtc_clk” 或者 “irc_osc”提供时钟。

      

      接下来该说如何配置时钟了:

      1、 配置CPU时钟(CCLK) :

      CPU时钟CCLK若是由PLL0提供的,那么PLL0会先将供给它的时钟进行升频,升频之后,再降频供CPU使用,即CCLK,

      至于为何要先升频再降频,暂时未知,也许单纯的是PLL的工作机制吧。以下即配置CPU时钟(CCLK)的具体过程:

      a、 描述主振荡器——即主振荡器大小范围多少,有没有稳定等,配置的寄存器为“SCS”。

      b、 配置外设时钟:

      这里要注意!按照正常思维顺序走的话,“b”这一步应该在所有步骤之后,,但是LPC17xx系列的MCU规定,在enable PLL0前,

      要先把外设时钟配置完成,所以,要先配置外设时钟。

      PLL0升频再降频后,会生成一个CCLK时钟,该CCLK经过再次分频即可得到所有外设的外设时钟。

      外设时钟的配置,既是根据各个外设的时钟需求,来分别独立的对CCLK分频取得。

      每个系列MCU均有其最大工作频率CCLK,以不超过该最大工作频率为准,配置CCLK降频(分频)大小的寄存器为“CCLKCFG”。

      配置外设时钟的寄存器分别为“PCLKSEL0/1”

      在配置外设时钟前,先考虑由PPL0升频多少降频多少才可得到想要的CCLK值,而这实际上是“d”步骤考虑的,所以此处的逻辑

      会有点乱。在阅读过程中,可跳过该步骤,直接看“c”步骤,最后跳回来看“b”步骤,但实际操作得按该步骤来。

      c、  从这三个振荡器选择供给PLL0的时钟,配置的寄存器为“CLKSRCSEL”。

      d、 配置“PLL0CFG”寄存器,来设置PLL0升频值及降频值的大小,寄存器截图如下:

      M即是倍频值,N即分频值,当使用晶振源为”rtc_clk”时,M值参照表4.8所建议的值。

      PLL0计算方法如下图:

        计算PLL0时,各个计算变量参数的意义如下图:

        

      e、 最后使能PLL0时钟并选择是否选用PLL0作为CCLK的输入时钟,操作的寄存器为“PLL0CON”

      f、  举个例子:MCU外接晶振为12MHZ,我需要CPU工作在频率100MHZ。那么根据式子,M = 100, N = 6。

      Fcco = (2 * 100 * 12MHZ) / 6 =400MHZ。然后4分频,最后得到CCLK为100MHZ。

      配置代码如下:

      

    #if (PLL0_SETUP)
      LPC_SC->PLL0CFG   = PLL0CFG_Val;
      LPC_SC->PLL0CON   = 0x01;             /* PLL0 Enable                        */
      LPC_SC->PLL0FEED  = 0xAA;
      LPC_SC->PLL0FEED  = 0x55;
      while (!(LPC_SC->PLL0STAT & (1<<26)));/* Wait for PLOCK0                    */
    
      LPC_SC->PLL0CON   = 0x03;             /* PLL0 Enable & Connect              */
      LPC_SC->PLL0FEED  = 0xAA;
      LPC_SC->PLL0FEED  = 0x55;
    #endif

      2、 USB时钟的配置:

      如整体时钟图示,USB时钟只能由PLL0或者PLL1提供,并且!若USB时钟由PLL0提供,那么PLL0的时钟源必须是外部 晶振!

      USB需要一个占空比为50%的48MHZ的时钟源,也就是说,PLL1或者PLL0分频出来的时钟Fcco必须为48MHZ的偶数倍数,

      以便为USB提供合适的时钟。

      A、 若由PLL0提供,那么由“1”步骤配置完PLL0,通过USB分频器获得满足条件的USB时钟即可。

      举个例子:USB的CLK要求为48MHZ,那么PLL0主频配置为48MHZ的偶数倍,然后通过USB时钟分频器分频,

      来获得符合要求的时钟。

      B、 若由PLL1提供,那么就得说说PLL1是如何配置的:

      a、 PLL1仅支持10MHZ到25MHZ范围内的时钟输入,且只能是外部时钟源,所以时钟源不用选择;

      b、 设置PLL1的“M”值与“P值”,PLL1类似于PLL0,也是会有一个先升频后降频的过程,但可以看出PLL1算是USB的一个

      特供时钟源,所以每个值的限制条件会比较多。

      PLL1输出频率的公式:

      Fcco频率可按如下公式计算:

      

      注意:

      Fosc(时钟源)的频率范围必须为10MHZ~25MHZ,

      USBCLK必须为48MHZ,

      Fcco的范围为:156MHZ~320MHZ;

      举个例子:

      输入的外部晶振为12MHZ,配置“M”的值为4,“P”的值为2,按公式计算可得PLL1升频后为192MHZ,然后分频到48MHZ

      供给USB使用。

          PLL1配置代码如下:

    #if (PLL1_SETUP)
      LPC_SC->PLL1CFG   = PLL1CFG_Val;
      LPC_SC->PLL1CON   = 0x01;             /* PLL1 Enable                        */
      LPC_SC->PLL1FEED  = 0xAA;
      LPC_SC->PLL1FEED  = 0x55;
      while (!(LPC_SC->PLL1STAT & (1<<10)));/* Wait for PLOCK1                    */
    
      LPC_SC->PLL1CON   = 0x03;             /* PLL1 Enable & Connect              */
      LPC_SC->PLL1FEED  = 0xAA;
      LPC_SC->PLL1FEED  = 0x55;
    #else
      LPC_SC->USBCLKCFG = USBCLKCFG_Val;    /* Setup USB Clock Divider            */
    #endif

      3、 看门狗wd_clk还未使用,下次要配时,再做记录。

    三、总结:

      不论是cotex-m3内核的LPC17xx系列、STM32系列,还是更高阶的arm9,arm11,时钟才是是摸透它们的最佳切入点。

      就实际使用来说,使用MCU既是使用各种外设,或者实现各种通信。不论何种外设,何种通信(UART、IIC、CAN、USB等),

      其能正确工作的关键就在于要给定正确合适的时钟。时钟的选法就采用MCU芯片手册上的时钟图来倒推回去,

      首先根据外设的需求确定外设时钟,接着考虑CPU的时钟,然后在反推到最初的时钟源的选择。

      完毕,在此做个记录,以便下次参考。

    记录地点:深圳WZ

    记录时间:2016年6月3日

  • 相关阅读:
    关于DOM节点的逆序
    javascript 巧妙的数组去重
    Canvas 学习笔记1
    web前端开发规范
    关于使用new和不使用new
    先知JS分享第二讲 数据类型与操作符
    关于谷歌console的小技巧
    菜鸟读jQuery 2.0.3 源码分析系列(2)
    菜鸟读jQuery 2.0.3 源码分析系列(1)
    local npm module ("*****") not found
  • 原文地址:https://www.cnblogs.com/ChYQ/p/5557511.html
Copyright © 2011-2022 走看看