dsp 28377 锁相环代码
半夜调试电机控制板的时候,最怕遇到时钟信号飘得亲妈都不认识。DSP 28377这货的锁相环配置说难不难,但手册里那些寄存器名字看得人眼晕。今天咱们直接扒开TI官方例程的裤衩,看看PLL到底怎么驯服。
先甩个祖传配置函数镇楼:
void InitPll(void) { volatile uint32_t i; // 先解除PLL的封印 SysCtrlRegs.PLLSTS.bit.MCLKSTS = 0; SysCtrlRegs.PLLSTS.bit.CLKSLIP = 0; // 切到安全模式 SysCtrlRegs.PLLCR.bit.PLLEN = 0; DELAY_US(100UL); // 老司机都懂的玄学延时 // 上硬菜——倍频系数 SysCtrlRegs.PLLCR.bit.DIV = 10; // 输入时钟×20 while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1) { // 死等锁相环上锁,此处适合点根烟 } // 切回PLL模式 SysCtrlRegs.PLLSTS.bit.MCLKCLR = 1; DELAY_US(100UL); // 再来个延时保平安 }重点来了,那个神秘的DIV值可不是随便填的。手册第183页偷偷写着计算公式:SYSCLK = (InputClk × [DIV+1])/2。假设外部晶振是10MHz,套用公式就是(10*(10+1))/2=55MHz?大兄弟你数学是体育老师教的吧?TI工程师在这儿埋了个坑——实际DIV寄存器值要减1!所以想得到200MHz主频的话,正确姿势是:
// 200MHz = (10MHz * (20 × 2)) SysCtrlRegs.SYSPLLMULT.all = 19; // 骚操作在这里调试时最刺激的莫过于手滑配置错时钟。有次我把DIV设成20,结果DSP当场表演死机绝活。后来用示波器抓OSCIN信号才发现,PLL锁不住的时候,时钟信号抖得像帕金森。这时候要在while循环里加个超时检测:
uint16_t timeout = 0; while((SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1) && (timeout < 5000)) { timeout++; DELAY_US(10); } if(timeout >= 5000) { ESTOP0; // 直接断头台伺候 }最后说个冷知识:修改PLL配置后,记得把flash等待周期调了。不然程序跑起来比树懒还慢。官方例程里藏着这么段代码:
FlashWdtRegs.FBAC.bit.WAIT = 0x1; // 200MHz对应1个等待周期时钟配好了别急着收工,拿CCS的寄存器观察窗口瞅瞅PLLSTS寄存器的LOCK位是不是稳如老狗。要是看到CLKSLIP位突然置1,八成是电源纹波太大——这时候该换电容还是改layout,自己看着办吧。