通俗点说,设置PLL锁相环就相当于超频,单片机超频的原因和PC机是一个道理。 分频的主要原因是外设需要的工作频率往往远低于CPU/MEMORY,这也和PC机南北桥的原理类似。
相对来说,PLL锁相环的设置还是比较简单的,因为东西很死,完全可以照搬。只是大家也不要太贪,设置太高相对来说不够稳定,进行过PC机超频的应该很有体会,一般我们现在用的XS128我觉得设置在80MHz是比较合适的,相比前几届比赛用的DG128,这个频率已经蛮高的了。还有就是SYNR,REFDV只有在CLKSEL_PLLSEL=0的情况下才能写入,不过这是系统默认状态。
多半大家可能还会有以下几点疑问:
1.PLL锁相环怎么设置?
答:通过写REFDV(CRG参考分频寄存器)和SYNR(CRG合成器寄存器)进行设置
2.代码里while(!CRGFLG_LOCK);这句是干什么的?
答:时钟校正同步
3.为什么代码中会有多多少少的几句空语句?
答:锁相环从设定到最后稳定还是需要一点点时间的,所以需要加几条空指令
/************************************************************************************** ------------------------------------ Code Warrior 5.0 Target : MC9S12XS128 Crystal: 16.000Mhz ============================================ 本程序主要包括以下功能: 设定系统工作在xxMHZ bus clock时钟下; by:庞辉 *****************************************************************************************/ #include <hidef.h> /* common defines and macros */ #include <MC9S12XS128.h> /* derivative information */ #pragma LINK_INFO DERIVATIVE "mc9s12xs128" void SetBusCLK_16M(void) { CLKSEL=0X00; // disengage PLL to system PLLCTL_PLLON=1; // turn on PLL SYNR=0x00 | 0x01; // VCOFRQ[7:6];SYNDIV[5:0] // fVCO= 2*fOSC*(SYNDIV + 1)/(REFDIV + 1) // fPLL= fVCO/(2 × POSTDIV) // fBUS= fPLL/2 // VCOCLK Frequency Ranges VCOFRQ[7:6] // 32MHz <= fVCO <= 48MHz 00 // 48MHz < fVCO <= 80MHz 01 // Reserved 10 // 80MHz < fVCO <= 120MHz 11 REFDV=0x80 | 0x01; // REFFRQ[7:6];REFDIV[5:0] // fREF=fOSC/(REFDIV + 1) // REFCLK Frequency Ranges REFFRQ[7:6] // 1MHz <= fREF <= 2MHz 00 // 2MHz < fREF <= 6MHz 01 // 6MHz < fREF <= 12MHz 10 // fREF > 12MHz 11 // pllclock=2*osc*(1+SYNR)/(1+REFDV)=32MHz; POSTDIV=0x00; // 4:0, fPLL= fVCO/(2xPOSTDIV) // If POSTDIV = $00 then fPLL is identical to fVCO (divide by one). _asm(nop); // BUS CLOCK=16M _asm(nop); while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it; CLKSEL_PLLSEL =1; //engage PLL to system; } void SetBusCLK_32M(void) { CLKSEL=0X00; // disengage PLL to system PLLCTL_PLLON=1; // turn on PLL SYNR =0x40 | 0x03; // pllclock=2*osc*(1+SYNR)/(1+REFDV)=64MHz; REFDV=0x80 | 0x01; POSTDIV=0x00; _asm(nop); // BUS CLOCK=32M _asm(nop); while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it; CLKSEL_PLLSEL =1; //engage PLL to system; } void SetBusCLK_40M(void) { CLKSEL=0X00; //disengage PLL to system PLLCTL_PLLON=1; //turn on PLL SYNR =0xc0 | 0x04; REFDV=0x80 | 0x01; POSTDIV=0x00; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=80MHz; _asm(nop); //BUS CLOCK=40M _asm(nop); while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it; CLKSEL_PLLSEL =1; //engage PLL to system; } void SetBusCLK_48M(void) { CLKSEL=0X00; //disengage PLL to system PLLCTL_PLLON=1; //turn on PLL SYNR =0xc0 | 0x05; REFDV=0x80 | 0x01; POSTDIV=0x00; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=96MHz; _asm(nop); //BUS CLOCK=48M _asm(nop); while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it; CLKSEL_PLLSEL =1; //engage PLL to system; } void SetBusCLK_64M(void) { CLKSEL=0X00; //disengage PLL to system PLLCTL_PLLON=1; //turn on PLL SYNR =0xc0 | 0x07; REFDV=0x80 | 0x01; POSTDIV=0x00; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=128MHz; _asm(nop); //BUS CLOCK=64M _asm(nop); while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it; CLKSEL_PLLSEL =1; //engage PLL to system; } void SetBusCLK_80M(void) { CLKSEL=0X00; //disengage PLL to system PLLCTL_PLLON=1; //turn on PLL SYNR =0xc0 | 0x09; REFDV=0x80 | 0x01; POSTDIV=0x00; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=160MHz; _asm(nop); //BUS CLOCK=80M _asm(nop); while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it; CLKSEL_PLLSEL =1; //engage PLL to system; } void SetBusCLK_88M(void) { CLKSEL=0X00; //disengage PLL to system PLLCTL_PLLON=1; //turn on PLL SYNR =0xc0 | 0x0a; REFDV=0x80 | 0x01; POSTDIV=0x00; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=176MHz; _asm(nop); //BUS CLOCK=88M _asm(nop); while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it; CLKSEL_PLLSEL =1; //engage PLL to system; } void SetBusCLK_96M(void) { CLKSEL=0X00; //disengage PLL to system PLLCTL_PLLON=1; //turn on PLL SYNR =0xc0 | 0x0b; REFDV=0x80 | 0x01; POSTDIV=0x00; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=192MHz; _asm(nop); //BUS CLOCK=96M _asm(nop); while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it; CLKSEL_PLLSEL =1; //engage PLL to system; } void SetBusCLK_104M(void) { CLKSEL=0X00; //disengage PLL to system PLLCTL_PLLON=1; //turn on PLL SYNR =0xc0 | 0x0c; REFDV=0x80 | 0x01; POSTDIV=0x00; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=208MHz; _asm(nop); //BUS CLOCK=104M _asm(nop); while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it; CLKSEL_PLLSEL =1; //engage PLL to system; } void SetBusCLK_120M(void) { CLKSEL=0X00; //disengage PLL to system PLLCTL_PLLON=1; //turn on PLL SYNR =0xc0 | 0x0d; REFDV=0x80 | 0x01; POSTDIV=0x00; //pllclock=2*osc*(1+SYNR)/(1+REFDV)=240MHz; _asm(nop); //BUS CLOCK=120M _asm(nop); while(!(CRGFLG_LOCK==1)); //when pll is steady ,then use it; CLKSEL_PLLSEL =1; //engage PLL to system; } void main(void) { EnableInterrupts; for(;;) { _asm(nop); } }
后面会尽快把PWM模块、AD模块、PIT模块等等都整理出来的……还请大家挑错或是共同讨论,共同进步嘛!
转载我博客文章郑重声明:技术性网站著名原创作者即可转载,商业性网站必须经过我的同意才能转载,否则追究责任——
pang123hui的博客:
博客园http://www.cnblogs.com/pang123hui/
CSDNhttp://blog.csdn.net/pang123hui/