PIC单片机时钟详解
最近在学PIC单片机,因此尝试写一篇文章记录一下。
单片机的型号为dsPIC33FJ16GS502,编辑器为MPLAB X IDE V6.00,编译器为:VC16 V2.00,这些工具都可以在Microchip的官网上可以下载安装。
1.时钟系统框图
首先来看一下单片机是时钟框图:

可以看到系统的时钟源可以来自3个部分:主振荡器、内部RC振荡器、内部低功耗RC振荡器.
而如何选择这些时钟作为系统时钟则是通过FOSCSEL寄存器的FNOSC位实现,其寄存器的功能如下:

那如何通过代码来实现对时钟的切换呢?常用的方法是在预编译指令设置,对相应的寄存器赋值即可。
以内部FRC振荡器为例,一行即可:
1 #pragma config FNOSC = FRCPLL //带PLL的快速RC振荡器(FRCPLL)

而如何设置寄存器的值呢?
有两种方法:
一种是查看用户手册;
一种是查看对应的头文件;在默认安装的情况下,头文件的路径为:
C:\Program Files (x86)\Microchip\xc16\v1.36\support\dsPIC33F\h\p33FJ16GS502.h
主振荡器的XT,HS,EC都是什么模式呢?
查看手册后可以得知:

细心的小伙伴可能,发现了系统框图中下边还有附属时钟(Auxiliary Clock),他是不可以作为系统时钟源的,其主要的功能是供给ADC模块和PWM模块的时钟,后面会做详细的介绍。
大概了解了系统时钟,本文下面将对每部分进行详细的讲解。
2.主振荡器
主振荡器就是采用外部晶振作产生时钟信号,本文的外部晶振为7.3728MHz,选取主振荡器作为系统时钟,主要有两条路径:

2.1 主振荡器方案
路径1的配置较为简单,通过预编译指令即可,见代码:
1 // FOSCSEL 2 #pragma config FNOSC = PRI //振荡器模式(不带PLL的XT) 3 #pragma config IESO = ON //内部外部切换模式(使用FRC启动设备,然后自动切换到用户选择的振荡器源) 4 // FOSC 5 #pragma config POSCMD = XT //主振荡器源(主振荡器XT) 6 #pragma config OSCIOFNC = OFF //OSC2引脚功能(OSC2引脚有时钟输出功能) 7 #pragma config IOL1WAY = ON //外设引脚选择配置(只允许一次重新配置) 8 #pragma config FCKSM = CSDCMD //时钟切换和监视器(无论时钟切换和故障保护时钟监视器被禁止)
由此可见经过上述一系列配置,达成的效果为:禁止时钟切换,禁止故障保护始终监视器,OSC2为数字IO引脚,选择主振荡器晶振模式作为系统时钟源。
经过上述配置Fosc = 7.3728MHz,其时钟频率由外部晶振决定。
2.1.2 主振荡器锁相环方案
路径2的配置过程较为麻烦,因为还需配置PLL,但是基本配置方法类似,见代码:
1 // FOSCSEL 2 #pragma config FNOSC = PRIPLL //振荡器模式(带PLL的XT) 3 #pragma config IESO = ON //内部外部切换模式(使用FRC启动设备,然后自动切换到用户选择的振荡器源) 4 // FOSC 5 #pragma config POSCMD = XT //主振荡器源(主振荡器XT) 6 #pragma config OSCIOFNC = OFF //OSC2引脚功能(OSC2引脚有时钟输出功能) 7 #pragma config IOL1WAY = ON //外设引脚选择配置(只允许一次重新配置) 8 #pragma config FCKSM = CSDCMD //时钟切换和监视器(无论时钟切换和故障保护时钟监视器被禁止)
发现其与路径1的区别只在第2行寄存值的改变,此时选择带PLL锁相环的路径故还需了解锁相环,以便计算相关频率。锁相环的框图在用户手册中如下:

其频率的计算公式为:


可以看到,PLL锁相环的输出与三个参数有关:PLLDIV,PLLPRE,PLLPOST。因此只要配置这三个参数即可得到我们想要的频率,常用的代码配置如下:
1 CLKDIVbits.PLLPRE = 0;//N1 = 2 7.3728MHz/2= 3.6864MHz 2 PLLFBDbits.PLLDIV = 41;//M = 43 3.6864*43 = 158.5152MHz 3 CLKDIVbits.PLLPOST = 0;//N2 = 2 158.5152/2 = 79.2576MHz
经过上述配置,Fosc = 79.2567MHz,时钟频率范围变化较大,可以在80MHz以下按照需要配置。
采用外部晶振作为是时钟源有着稳定性较高的优点,但是考虑的经济性,外部晶振相对与内部振荡器而言,经济性较差,故在对经济性敏感的产品中常采用内部晶振。
3.内部RC振荡器
此款单品的内部RC振荡器为7.3728MHz,速度快,成本低。其主要有4条路径:

四条路径的输出频率范围见表:
| 路径 | 频率(MHz) |
| 1 | <80MHz |
| 2 | 0.46MHz~7.37MHz |
| 3 | 0.46MHz |
| 4 | 7.37Mhz |
3.1 FRC和FRCDIV16方案
路径3,4设置比较简单,仅需设置一个寄存器即可,见代码:
1 #pragma config FNOSC = FRC // FRC 模式 2 #pragma config FNOSC = FRCDIV16 // FRC的16分频
3.2 FRCDIV方案
路径2的设置也相对简单,除设置时钟选择寄存器外,还需设置FRC分频寄存器FRCDIV,寄存器与具体分频系数见图:

具体配置见代码
1 #pragma config FNOSC = FRCDIV
主程序代码:
1 void FRCDIV_Init(void) 2 { 3 CLKDIVbits.FRCDIV = 0; // 1分频 4 }
3.3 FRCPLL方案
路径1需要经过PLL锁相环,其频率可以上升的更高,当然配置麻烦一点,见代码:
1 #pragma config FNOSC = FRCPLL //带PLL的快速RC振荡器(FRCPLL)
PLL配置程序:
1 void System_Colck(void) 2 { 3 CLKDIVbits.PLLPRE = 0;//N1 = 2 7.3728MHz/2= 3.6864MHz 4 PLLFBDbits.PLLDIV = 41;//M = 43 3.6864*43 = 158.5152MHz 5 CLKDIVbits.PLLPOST = 0;//N2 = 2 158.5152/2 = 79.2576MHz 6 }
经过上述配置,其时钟频率为79.2576MHz。
4.低功耗RC振荡器
低功耗RC时钟一般供给看门狗定时器,上电延时定时器和故障保护定时器使用。一般不作为系统主时钟,故不再描述如何配置配置,有需要的小伙伴可以自行探索。
5.附属时钟
附属时钟是高速10位ADC和高速PWM的时钟源,其最高可达到120MHz的频率。
其配置相对较为简单,照着框图,写寄存器就好了,框图如下:

可以看到附属时钟源的时钟来源有三个:主振荡器,主振荡器经PLL锁相环,内部RC振荡器。
本文以内部RC振荡器为例,给出配置代码如下:
1 /* 2 * 函数功能:附属时钟ACLK初始化 3 * 注意事项:附属时钟的最大输出频率为:7.37 * 16 = 117.92MHz 4 * 参数说明:ACLK_Div:分频系数 5 * 参数 7 6 5 4 3 2 1 0 6 * 分频比 1 2 4 8 16 32 64 256 7 */ 8 void ALCK_Init(unsigned char ACLK_Div ) 9 { 10 ACLKCONbits.ASRCSEL = 0 ; // Don't select any clock as ACLK input 11 ACLKCONbits.FRCSEL = 1 ; // Select FRCCLK as ACLK input 12 ACLKCONbits.ENAPLL = 1 ; // Enable Auxiliary PLL 13 ACLKCONbits.SELACLK = 1 ;// Auxiliary PLL Clock Provides the Clock sourse 14 ACLKCONbits.APSTSCLR = ACLK_Div ;// Set Divide Auxiliary colck by 1 15 while(ACLKCONbits.APLLCK != 1); // Wait for Auxiliary PLL to ready 16 }
代码较为简单,清晰明了,不再进行解读啦。
6.总结:
至此PIC单片机的时钟系统大部分已经解读完毕了,还有一些剩余部分,后期可能会有补充。
本人第一篇文章,文笔青涩,如有错误,欢迎指出。未经允许,禁止转载。

浙公网安备 33010602011771号