本帖最后由 JackTang1994 于 2021-9-26 14:03 编辑
硬件平台:PIC16(L)F1826、MPLAB ICD4调试器
软件平台:MPLAB X IDE V5.5、MPLAB Code Configurator V4
PIC16(L)F1826数据手册:https://www.microchip.com/content/dam/mchp/documents/OTH/ProductDocuments/DataSheets/41391D.pd
示例工程:
OSC_Switch.X.zip
(134.36 KB)
说明这里我们只介绍内部时钟源内的切换,而如果需要设置时钟模式则设置配置字1中的FOSC<2:0>位。
芯片手册阅读
阅读手册第5章:5.0OSCILLATOR MODULE (WITH FAIL-SAFE CLOCK MONITOR)
MCU时钟框图
从框图中我们可以知道CPU时钟来源有3个:外部晶振、Timer1、内部时钟
内部时钟源(INTERNAL CLOCK SOURCES)HFINTOSC:内部高速时钟,有31.25 kHz、125 kHz、250 kHz、500 kHz、1 MHz、2 MHz、4 MHz、8 MHz 或 32 MHz、16MHz频率
MFINTOSC:内部中速时钟,有31.25 kHz、62.5 kHz、125 kHz、250 kHz、500 kHz频率
LFINTOSC:内部低速时钟,只有31 kHz频率
内部时钟源切换
内部时钟源切换就是HFINTOSC、MFINTOSC、LFINTOSC之间切换,不同时钟源之间切换时,新的时钟可能还处理关闭状态所以在设置时钟切换时有一个延时。我们可以通过OSCSTAT寄存器判断时钟是否已经切换完成。
内部时钟源频率及设置
时钟切换时序
在时钟没有切换完毕时,MCU一直使用以前的时钟频率,当完成切换时MCU系统频率就会切换成设置的值.所以这里的Start-up time不是MCU不运行代码的空闲等待时间而是时钟切换电路反应时间.所以我们不必加NOP延时,而是直接判断OSCSTAT的Ready标志位。
时钟切换成功标志
通过读取OSCSTAT寄存器中的HFIOFR、MFIOFR、LFIOFR即可知道当前切换到HFINTOSC、MFINTOSC、LFINTOSC内部时钟源是否已经准备好了。
MCC配置
MCC的时钟配置,按照下图设置即可
代码编写
在main.c文件中添加以下代码:定义时钟频率设置值,并编写了一个时钟配置函数通过判断OSCSTAT寄存器中相应的时钟准备位来判断切换后时钟是否已经准备好了,从而决定是否需要继续操作相关外设
typedef enum internal_CLK
{
OSC_31K_LF = 0x00, OSC_31K25_MF = 0x02, OSC_31K25_HF = 0x03, \
OSC_62K5_MF = 0x04, OSC_125K_MF = 0x05, OSC_250K_MF = 0x06, \
OSC_500K_MF = 0x07, OSC_125K_HF = 0x08, OSC_250K_HF = 0x09, \
OSC_500K_HF = 0x0A, OSC_1M_HF = 0x0B, OSC_2M_HF = 0x0C, \
OSC_4M_HF = 0x0D, OSC_8M_HF = 0x0E, OSC_16M_HF = 0x0F
}INT_CLK_FREQ_TypeDef;
void Set_SysInternal_Freq(INT_CLK_FREQ_TypeDef clock_freq)
{
OSCCONbits.SCS = 0x02; // internal oscillator
OSCCONbits.IRCF = clock_freq; // start-up clock
switch(clock_freq)
{
case OSC_31K_LF:
while(OSCSTATbits.LFIOFR != 0x01);
break;
case OSC_31K25_MF:
case OSC_62K5_MF:
case OSC_125K_MF:
case OSC_250K_MF:
case OSC_500K_MF:
while(OSCSTATbits.MFIOFR != 0x01);
break;
case OSC_31K25_HF:
case OSC_125K_HF:
case OSC_250K_HF:
case OSC_500K_HF:
case OSC_1M_HF:
case OSC_2M_HF:
case OSC_4M_HF:
case OSC_8M_HF:
case OSC_16M_HF:
while(OSCSTATbits.HFIOFR != 0x01);
break;
default:
break;
}
}
由于MPLAB X IDE单纯的软件仿真无法仿真时钟,所以这一次我们使用调试器来仿真并观察现象。软件仿真时的程序运行时钟频率是预先设置好的,无法后期修改。如下图所示:
注:关于时钟相关的仿真,无法使用MPLAB X IDE的软件仿真来观察结果。
工程设置
在工程设置中选择调试器,然后在调试器设置窗口选择使用调试器供电.
注:这个需要根据不同调试器来进行设置,我这里使用的是ICD4调试器
将程序停止在函数处,此时软件使用默认的时钟500KHZ
通过将CLKOUT引脚接示波器上观察波形就是125KHZ(Fosc / 4).这个是CLKOUT输出的时钟为系统时钟的4分频
从手册中我们也可以知道,MCU复位后的时钟频率
运行完SYSTEM_Initialize()函数
在Set_SysInternal_Freq(OSC_31K25_HF);语句处打一个断点,此时程序只是运行完了SYSTEM_Initialize()函数,但是还没有运行Set_SysInternal_Freq(OSC_31K25_HF);语句,CLKOUT输出波形为MCC软件自动生成的代码中设置的系统频率。
此时频率约1.75MHZ。不知道为啥这个时钟频率不是系统时钟的1/4,即16/4 = 4MHZ。
运行完Set_SysInternal_Freq()函数。
此时系统时钟已经是我们设置的31.25KHZ时钟源为HFINTOSC
|