怎样只用一个XT2晶振得到精确的高频----msp430f5529单片机

Joyin   2012-5-11 19:59 楼主
    这个从我CSDN博客里面转过来,╮(╯▽╰)╭,我才明白CSDN是网络技术的主场,所以果断放弃了CSDN,转投这里了
    最近在用msp430f5529,终于在上周弄清了时钟方面的原理,在此记录下
 
    由用户指导时钟那一章可以看出MSP430单片机5系列的ACLK、SMCLK、MCLK都可以由XT1CLK/VLOCLK/REFOCLK/DCOCLK/DCOCLKDIV/XT2CLK得到,而TI例程里面给的大多是由FLLREFCLK倍频得到DCOCLK或DCOCLK,从而得到SMCLK和MCLK,而ACLK都是由XT1CLK或REFOCLK直接获得。例程里面的FLLREFCLK来源于XT1CLK或REFOCLK。所以例程里面得到的高频都是经过大的倍频得到,这里面有个弊端,就是如果你需要很精确的频率的话由大的倍频得到的频道误差大。
    这里呢我就讲下怎么只用一个高频晶振得到ACLK/SMCLK/MCLK,我只用了XT2,没有用XT1。由XT2得到XT2CLK=4MHz,然后将XT2CLK作为FLLREFCLK的时钟源,也就是FLLREFCLK现在是4MHZ了,不是32khz了。通过下面的公式得到DCOCLK:

f(DCOCLK)=D*(N+1)*(f(FLLREFCLK)/n)

默认情况下,D=2,n=1,N是自己随意配置的整数。这里我要得到DCLCLK=16MHZ,我取的是D=16,N=1,n=8,当然你可以自己计算,不限于这个值。由DCOCLK/D=DCOCLKDIV,最终由DCOCLKDIV分频得到ACLK=31.5khz,当然跟32khz相差还挺大的,我也没有办法了。

    另外也要扩大DCO倍频的赔率范围,5529数据手册上有指示的。特别要注意的是,这里你千万不能打开XT1,会出错的。最后,我帖上我的的程序,已经验证过了完全正确的

 P1DIR |= BIT0;
 P1SEL |= BIT0;              //可以看ACLK的频率
 P2DIR |= BIT2;
 P2SEL |= BIT2;             //SMCLK
 P7DIR |= BIT7;
 P7SEL |= BIT7;             //MCLK

 P5SEL |= BIT2+BIT3;
 UCSCTL6 &= ~XT2OFF;          //打开XT2

/*********************寄存器配置部分******************************/

 __bis_SR_register(SCG0);
 UCSCTL0 = DCO0+DCO1+DCO2+DCO3+DCO4;
 UCSCTL1 = DCORSEL_4;                    //DCO频率范围在28.2MHZ以下
 UCSCTL2 = FLLD_4 + 1;                   //D=16,N=1
 UCSCTL3 = SELREF_5 + FLLREFDIV_3;       //n=8,FLLREFCLK时钟源为XT2CLK;DCOCLK=D*(N+1)*(FLLREFCLK/n);DCOCLKDIV=(N+1)*(FLLREFCLK/n);
 UCSCTL4 = SELA_4 + SELS_3 +SELM_3;      //ACLK的时钟源为DCOCLKDIV,MCLK\SMCLK的时钟源为DCOCLK
 UCSCTL5 = DIVA_5 +DIVS_1;               //ACLK由DCOCLKDIV的32分频得到,SMCLK由DCOCLK的2分频得到
                                         //最终MCLK:16MHZ,SMCLK:8MHZ,ACLK:32KHZ
 
 __bic_SR_register(SCG0);                //Enable the FLL control loop

/**********************************************************************/

 __delay_cycles(8192);
 do
 {
  UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); //Clear XT2,XT1,DCO fault flags
  SFRIFG1 &= ~OFIFG;       //Clear fault flags
 }while (SFRIFG1&OFIFG);

回复评论 (14)

回复 楼主 Joyin 的帖子

你好,我问一下,为什么我直接用XT2CLK的时钟只有1MHz啊
我是这样配置的:
  UCSCTL4 |= SELS_5 + SELM_5;     // Set SMCLK,MCLK = XT2CLK
  UCSCTL5 |= DIVS_0 + DIVM_0;     // SMCLK/1
  UCSCTL6 &= ~XT2OFF;             // XT2CLK Enable
  do
  {
    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
    SFRIFG1 &= ~OFIFG;
  }while (SFRIFG1&OFIFG);
很简单的配置,但是出来看时钟波形,就只有1M的频率,能帮我解答一下吗
点赞  2013-4-19 16:29

回复 楼主 Joyin 的帖子

欢迎来到MSP430版块,这里是MSP430的主场
《MCU工程师炼成记》作者之一
点赞  2013-4-19 20:55

回复 沙发 yunhaiking 的帖子

是不是外部XT2没有成功,而是使用了DCO。
点赞  2013-4-20 16:11

回复 4楼 hjf2002 的帖子

可以怎么测试它呢
点赞  2013-4-20 16:52

回复 5楼 yunhaiking 的帖子

找个MSP430F5529 的TI 的example测试一下。
点赞  2013-4-20 18:49

回复 6楼 hjf2002 的帖子

找了个demo程序,运行是对的,证明是XT2接上了,发现我的配置没有这条语句
P5SEL |= BIT2+BIT3;   // Port select XT2
点赞  2013-4-20 19:41
搭楼同问。我这个是m430f2619实验板的自带程序,外部晶振16MHz。这个函数是不是设置MCLK接外部晶振,外部晶振是不是接XT2的。
void Init_CLK( void )
{
        int i;
    BCSCTL3 |= XT2S_2;                         // XT2频率范围设置
    BCSCTL1 &= ~XT2OFF;                        // 打开XT2振荡器
    BCSCTL1 |= DIVA_1;                         // ACLK/2
    do
    {
        IFG1 &= ~OFIFG;                        // 清振荡器失效标志
        BCSCTL3 &= ~XT2OF;                     // 清XT2失效标志
        for(  i = 0x47FF; i > 0; i-- );    // 等待XT2频率稳定
    }while (IFG1 & OFIFG);                     // 外部时钟源正常起动了吗?
    BCSCTL2 |= SELM_2 + SELS + DIVS_2 ;        // 设置MCLK、SMCLK为XT2
}
如果是设置为16MHz的话。这个延时误差大不大。
#define CPU_F                                 ((double)16000000)                                        //频率
#define delay_ms(x)                 __delay_cycles((long)(CPU_F*(double)x/1000.0))
msp430的时钟设置实在不是很明白,请高手指点下。谢谢。
点赞  2013-4-22 00:04

回复 8楼 kubiaaa 的帖子

16MHz的晶振是接在XT2上,上面的代码选定了XT2的振荡频率作为CPU和外设的SMCLK的时钟。
《MCU工程师炼成记》作者之一
点赞  2013-4-22 10:29

回复 9楼 wstt 的帖子

谢谢,明白了。那这个毫秒级的延时delay_ms(x)大致上误差不大吧。指令周期是1/16MHz吗??
点赞  2013-4-22 15:39

回复 10楼 kubiaaa 的帖子

__delay_cycles这个函数我没有用过,是库函数么?
《MCU工程师炼成记》作者之一
点赞  2013-4-23 14:14

回复 11楼 wstt 的帖子

我觉得是汇编函数吧, 我网上找的。其实我还想问下,这些us级的延时,怎么样做才比较好
点赞  2013-4-23 17:12

回复 12楼 kubiaaa 的帖子

us级的延时,在MCLK16M的情况下,大概就16个指令周期,可以用_NOP();做一个周期。
你这个函数应该效果是一样的。
《MCU工程师炼成记》作者之一
点赞  2013-4-23 23:56

回复 13楼 wstt 的帖子

终于搞懂了,谢谢版主
点赞  2013-4-24 08:49

回复 14楼 kubiaaa 的帖子

《MCU工程师炼成记》作者之一
点赞  2013-4-24 13:33
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复