[资料分享] MSP430时钟DCO及DCO_DIV配置过程

火辣西米秀   2020-10-10 20:15 楼主

DCO及DCO_DIV配置过程
由于DCO是可以自主倍频的,倍频函数为CLOCK_DCO_PLLConfig(FLLREF_Source, FLLREF_DIVx, uint32_t DCO_FLL_Fre),由于DCO_DIV分频为1且不允许修改,即DCO_DIV与DCO同频,下面好好分析一下倍频过程

1 .时钟分频系数,共计6种选择
typedef enum
{
  FLLREF_DIV_1     ,   //不分频
  FLLREF_DIV_2     ,   //二分频
  FLLREF_DIV_4     ,   //四分频
  FLLREF_DIV_8     ,   //八分频
  FLLREF_DIV_12    ,   //十二分频
  FLLREF_DIV_16    ,   //十六分频
}FLLREF_DIVx;    //FLL参考时钟分频

2. 参考分频时钟,总计3个
typedef enum
{
  FLLREF_XT1    =0u,    //32.768k
  FLLREF_REFO   =2u,    //10k
  FLLREF_XT2    =5u     //4M
}FLLREF_Source;  //FLL参考时钟源

3 .倍频函数
/*******************************************************************************
*  函数名称:CLOCK_DCO_PLLConfig(FLLREF_Source refsource, FLLREF_DIVx refdiv, uint32_t DCO_FLL_Fre)
*  功能说明:设置DCO频率,单位(HZ)
*  参数说明:FLLREF_Source refsource :参考时钟源
             FLLREF_DIVx refdiv      :参考时钟源分频系数
             uint32_t DCO_FLL_Fre      :DCO设置频率
*  函数返回:无
********************************************************************************/
void CLOCK_DCO_PLLConfig     (FLLREF_Source refsource, FLLREF_DIVx refdiv, uint32_t DCO_FLL_Fre)
{
  static const uint16_t ref_div_value[6]={1,2,4,8,12,16};
  /*根据频率提高内核电压*/
  //SetVcoreUp ( (DCO_FLL_Fre < 12MHz) ? 0 : ((DCO_FLL_Fre < 16MHz) ? 1 : ((DCO_FLL_Fre < 20MHz) ? 2 :3))); //设置内核电压
  if(DCO_FLL_Fre < 12MHz)
    SetVcoreUp (0x00);                      //设置内核电压
  else if(DCO_FLL_Fre < 16MHz)
    SetVcoreUp (0x01);       
  else if(DCO_FLL_Fre < 20MHz)
    SetVcoreUp (0x02);       
  else
    SetVcoreUp (0x03);       

  __bis_SR_register(SCG0);                  // 禁止倍频环FLL,
  UCS->CTL0 = 0x0000;                       // 清零 DCOx, MODx

  if (DCO_FLL_Fre < 0.63MHz)         //           fsystem < 0.63MHz
    UCS->DCORSEL = 0;
  else if (DCO_FLL_Fre < 1.25MHz)    // 0.63MHz < fsystem < 1.25MHz
    UCS->DCORSEL = 1;
  else if (DCO_FLL_Fre < 2.5MHz)     // 1.25MHz < fsystem <  2.5MHz
    UCS->DCORSEL = 2;
  else if (DCO_FLL_Fre <   5MHz)     // 2.5MHz  < fsystem <    5MHz
    UCS->DCORSEL = 3;
  else if (DCO_FLL_Fre <  10MHz)     // 5MHz    < fsystem <   10MHz
    UCS->DCORSEL = 4;
  else if (DCO_FLL_Fre <  20MHz)     // 10MHz   < fsystem <   20MHz
    UCS->DCORSEL = 5;
  else if (DCO_FLL_Fre <  40MHz)     // 20MHz   < fsystem <   40MHz
    UCS->DCORSEL = 6;
  else
    UCS->DCORSEL = 7;

  UCS->FLLREFDIV = refdiv;
  UCS->SELREF = refsource;

  float Fref_value;
  if(refsource == FLLREF_XT2)
  {
    XT2_Config(TRUE);
    Fref_value = (float)((uint32_t)EXTAL_IN_XT2_HZ/ref_div_value[refdiv]);  
  }
  else if(refsource == FLLREF_XT1)
  {
    XT1_Config(TRUE);
    Fref_value = (float)(EXTAL_IN_XT1_HZ/ref_div_value[refdiv]);
  }
  else if(refsource == FLLREF_REFO)
  {
    Fref_value = (float)(REFOCLK_FREQUENCY/ref_div_value[refdiv]);
  }
  uint16_t FLLN_VALUE = (uint16_t)((DCO_FLL_Fre/Fref_value+0.5f)-1u);
  ASSERT(FLLN_VALUE < 1024,"CLOCK_DCO_PLLConfig","FLLN_VALUE不允许超过1023,请将DCO频率设低或者更换为更高频率的参考时钟源!");         //不允许超过1023,请将DCO频率设低或者更换为更高频率的参考时钟源

  g_sClock.DCO_FLL_Frequency = DCO_FLL_Fre;

  UCS->FLLN = FLLN_VALUE;        //
  UCS->FLLD = 0;     //设置DCO分频  

  __bic_SR_register(SCG0);                  // 使能FLL
  do
  {
    UCS->DCO_FFG = RESET; // 清除,CLOCK_DCO 失效标志                                        
    SFRIFG1 &= ~OFIFG;                                             // 清除时钟失效标志
  }while (UCS->DCO_FFG == BIT_SET);                                           // 检查DCO失效标志
  //将使用DCO作为时钟源的时钟频率值修改
  if(UCS->SELM == CLOCK_DCO || UCS->SELM == CLOCK_DCO_DIV)
  {
    CLOCK_DIVx div = (CLOCK_DIVx)UCS->DIVM;
    CLOCK_MCLK_Config ((CLOCK_Source)UCS->SELM, div);
  }

  if(UCS->SELS == CLOCK_DCO || UCS->SELS == CLOCK_DCO_DIV)
  {
    CLOCK_DIVx div = (CLOCK_DIVx)UCS->DIVS;
    CLOCK_SMCLK_Config((CLOCK_Source)UCS->SELS, div);
  }

  if(UCS->SELA == CLOCK_DCO || UCS->SELA == CLOCK_DCO_DIV)
  {
    CLOCK_DIVx div = (CLOCK_DIVx)UCS->DIVA;
    CLOCK_ACLK_Config ((CLOCK_Source)UCS->SELS, div);
  }
}

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复