一、锁相环介绍
在前面的几个实验中,我们没有涉及到单片机的总线时钟的设置。这是因为飞思卡尔16位单片机在不进行总线时钟设置的情况下默认的总线时钟为外部输入晶振频率的1/2。我们的实验电路中用的外部晶振的频率为16MHz,所以在不设置总线时钟的情况下,总线时钟频率为8MHz。在工程应用中,8MHz的总线频率比较低,XEP100单片机允许总线频率为40MHz,实际测试最高可以运行在80MHz的总线频率下。但不建议设置过高的总线频率,原因之一是频率越高稳定性越差;另外过高的总线频率会影响芯片的寿命。为了获得比较高的总线频率,就需要使用锁相环,通过锁相环(PLL)可以对晶振频率进行倍频,从而形成比较高的总线频率。锁相环模块的功能框图如下图所示
这里只介绍两个比较重要的参数SYNDIV和REFDIV,总线时钟通过这两个参数计算得到,计算公式如下:
其中,
是晶振的频率
SYNDIV和REFDIV这两个参数通过设置REFDV和SYNR这两个寄存器中的SYNDIV和REFDIV位进行修改。
二、实例测试
我们通过一个简单的实验来了解锁相环的用法,在本文的资源中,可以下载例程的代码。
代码的主要部分是对锁相环的初始化,代码如下:
#define BUS_CLOCK 80000000 //总线频率
#define OSC_CLOCK 16000000 //晶振频率
/*************************************************************/
/* 初始化锁相环 */
/*************************************************************/
void INIT_PLL(void)
{
CLKSEL &= 0x7f; //设置OSCCLK作为系统时钟
PLLCTL &= 0x8F; //禁止锁相环
//PLLCLK=2×OSCCLK×(SYNDIV+1)/(REFDIV+1), fbus=PLLCLK/2
#if(BUS_CLOCK == 120000000)
SYNR = 0xcd;
#elif(BUS_CLOCK == 104000000)
SYNR = 0xcc;
#elif(BUS_CLOCK == 96000000)
SYNR = 0xcb;
#elif(BUS_CLOCK == 88000000)
SYNR = 0xca;
#elif(BUS_CLOCK == 80000000)
SYNR = 0xc9;
#elif(BUS_CLOCK == 72000000)
SYNR = 0xc8;
#elif(BUS_CLOCK == 64000000)
SYNR = 0xc7;
#elif(BUS_CLOCK == 56000000)
SYNR = 0xc6;
#elif(BUS_CLOCK == 48000000)
SYNR = 0xc5;
#elif(BUS_CLOCK == 40000000)
SYNR = 0x44;
#elif(BUS_CLOCK == 32000000)
SYNR = 0x43;
#elif(BUS_CLOCK == 24000000)
SYNR = 0x42;
#elif(BUS_CLOCK == 16000000)
SYNR = 0x01;
#endif
REFDV = 0x81;
PLLCTL |=0x70; //使能锁相环
asm NOP;
asm NOP;
while(!(CRGFLG&0x08)); //PLLCLK锁定
CLKSEL |= 0x80; //设置PLLCLK为系统时钟
}
这段代码比较简单,主要是根据期望的总线频率BUS_CLOCK,对SYNR和REFDV寄存器进行设置,然后通过PLLCTL寄存器使能锁相环,然后等待锁相环工作稳定,最后把单片机的总线时钟源设置为锁相环时钟。
在上面的代码中,我们看到条件判断语句前边都带有“#”,这与不带“#”的条件有什么区别呢?
带“#”的代码称为预处理部分。所谓预处理是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作。通俗一些说:预处理命令是由编程软件完成的,而不是有单片机完成的。例如:本实验的代码中定义了BUS_CLOCK为80000000,所以经过编程软件处理之后,最后这段代码等效于SYNR=0xc9;,而不是将这段代码都下载到单片机中。
预处理是C语言的一个重要功能,它由预处理程序负责完成。当对一个源文件进行编译时,系统将自动引用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。C语言提供了多种预处理功能,如宏定义、文件包含、条件编译等。合理地使用预处理功能编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计。
在程序的主函数中,也比较简单,就是一段闪灯的代码。
将程序下载到单片机中运行,可以看到LED灯快速闪烁。
将程序的主函数中的设置锁相环的语句打双斜线//INIT_PLL();,使此句隐去,即不对锁相环进行设置,此时总线频率为8MHz。然后将程序再次烧写到单片机中运行,可以看到LED灯的闪烁频率明显降低。