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);
}
}