CMT2380F32模块开发5-CLK例程
Posted andylauren
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CMT2380F32模块开发5-CLK例程相关的知识,希望对你有一定的参考价值。
时钟控制模块主要控制系统时钟以及外设时钟,可以配置不同的时钟源作为系统时钟、可以配置不同的系统时钟分频、可以启动或禁用外设时钟,另外为了确保高精度,内部时钟都具有校准功能。
本产品支持以下四个不同的时钟源作为系统时钟:
内部高速 RC 时钟 RCH(4M)(默认主频)
外部低速晶振时钟 XTL
内部低速 RC 时钟 RCL(38.4K 与 32.768K 可配置)
外部高速晶振时钟 XTH
芯片上电或复位后的默认时钟源为频率为4MHz 的内部高速时钟;当系统进入Deep Sleep,此高速时钟会自动关闭。
出厂时已预调好的5 个频率4MHz、8MHz、16MHz、22.12MHz、24MHz.
内部低速时钟可供选择的频率为 38.4KHz、32.768KHz。当系统进入 Deep Sleep,此低速时钟不会自动关闭,超低功耗外设模块可以选择 RCL 作为其时钟。
外部低速晶振时钟需外接一个32.768KHz 的低功耗晶振,当系统进入Deep Sleep,此低速时钟不会自动关闭。超低功耗模式下工作的外设模块可以选择XTL作为其时钟。
外部 4M~32M 晶振时钟需根据用户系统需求外接一个 4M~32M 的高速晶振。
由于模块没有外接晶振,所以代码不可以切换为外部晶振,否则会死循环在晶振启动检测。
这部分的例程主要是配置时钟,然后将时钟从IO输出,一般需要使用示波器或者逻辑分析仪查看波形频率,如果没有设备就看看代码,知道怎么设置就行了,基本不会出错,除非你使用了自己的板子,接了外部晶振,需要测试之类的。
clk_init例程
这个例程将swd管脚配置为HCLK输出,所以必须使用IO作为触发,否则以后就无法下载了。
//外部SW1控制程序是否继续运行
SK_SW1_INIT();
while (TRUE == SK_SW1_GET())
;
//设置P31为时钟输出IO
Clk_SetFunc(ClkFuncSwdPinIOEn, TRUE);
Gpio_SetFunc_HCLKOUT_P31();
// CLK初始化
DDL_ZERO_STRUCT(stcCfg);
stcCfg.enClkSrc = ClkRCH;
stcCfg.enHClkDiv = ClkDiv128;
stcCfg.enPClkDiv = ClkDiv8;
Clk_Init(&stcCfg);
用示波器查看P31引脚,默认内部HCLK = 4M 示波器频率= 4M/128 = 32KHz。
clk_div例程
这个例程本来是对外部时钟分频的,由于模块没有外部时钟,所以这里改成了对内部时钟分频,就和clk_init一样了。
clk_switch例程
这个例程举例了时钟模块频率切换的过程,还是用示波器查看P31管脚,按下一次按键切换一次频率。
// SW1控制程序是否继续运行
SK_SW1_INIT();
while (TRUE == SK_SW1_GET())
;
//设置P31为HCLK输出
Clk_SetFunc(ClkFuncSwdPinIOEn, TRUE);
Gpio_SetFunc_HCLKOUT_P31();
u32Val = Clk_GetHClkFreq();
//系统时钟频率设置与切换
// RCH 4MHz
Clk_SwitchTo(ClkRCL);
Clk_SetRCHFreq(ClkFreq4Mhz);
Clk_SwitchTo(ClkRCH);
u32Val = Clk_GetHClkFreq();
while (TRUE == SK_SW1_GET())
;
// RCH 8MHz
Clk_SwitchTo(ClkRCL);
Clk_SetRCHFreq(ClkFreq8Mhz);
Clk_SwitchTo(ClkRCH);
u32Val = Clk_GetHClkFreq();
while (TRUE == SK_SW1_GET())
;
// RCH 16MHz
Clk_SwitchTo(ClkRCL);
Clk_SetRCHFreq(ClkFreq16Mhz);
Clk_SwitchTo(ClkRCH);
u32Val = Clk_GetHClkFreq();
while (TRUE == SK_SW1_GET())
;
// RCH 22.12MHz
Clk_SwitchTo(ClkRCL);
Clk_SetRCHFreq(ClkFreq22_12Mhz);
Clk_SwitchTo(ClkRCH);
u32Val = Clk_GetHClkFreq();
while (TRUE == SK_SW1_GET())
;
// RCH 24MHz
Clk_SwitchTo(ClkRCL);
Clk_SetRCHFreq(ClkFreq24Mhz);
Clk_SwitchTo(ClkRCH);
u32Val = Clk_GetHClkFreq();
while (TRUE == SK_SW1_GET())
;
// RCL 38.4K
Clk_SetRCLFreq(ClkFreq38_4K);
Clk_SwitchTo(ClkRCL);
u32Val = Clk_GetHClkFreq();
while (TRUE == SK_SW1_GET())
;
// RCL 32768
Clk_SetRCLFreq(ClkFreq32768);
u32Val = Clk_GetHClkFreq();
while (TRUE == SK_SW1_GET())
;
///< \\todo check 2nd version
Clk_SwitchTo(ClkRCL);
Clk_SetRCHFreq(ClkFreq4Mhz);
Clk_SwitchTo(ClkRCH);
u32Val = Clk_GetHClkFreq();
clk_stb_time例程
这个例程展示时钟模块的晶振稳定时间的设置方法,查看示波器,测量P34低电平时间是否大于设定的稳定时间。
// SW1控制程序是否继续执行
SK_SW1_INIT();
while (TRUE == SK_SW1_GET())
;
#if 1 // RCL
// stable time
Clk_SetRCL_StableTime(ClkCycle256);
// enable new clock
M0P_CLOCK->SYSCTRL2 = 0x5A5A;
M0P_CLOCK->SYSCTRL2 = 0xA5A5;
M0P_GPIO->P3OUT_f.P34 = 0;
M0P_CLOCK->SYSCTRL0_f.RCL_EN = TRUE;
// check stable
while (FALSE == M0P_CLOCK->RCL_CR_f.STABLE)
;
M0P_GPIO->P3OUT_f.P34 = 1;
// switch new
M0P_CLOCK->SYSCTRL2 = 0x5A5A;
M0P_CLOCK->SYSCTRL2 = 0xA5A5;
M0P_CLOCK->SYSCTRL0_f.CLK_SW4_SEL = ClkRCL;
delay1ms(100);
Clk_SwitchTo(ClkRCH);
clk_systick例程
处理器中有一个称为 SysTick 的简单定时器,用于产生周期性的中断请求。
连接P34到示波器,查看P34频率是否为500Hz。
这个部分有意思的是,文档给了不同时钟下的溢出周期设置值,《AN220-CMT2380F32用户指南(微控制器部分)-CN-V1.0-20200107》P322,但是根据公式却算不出来,可能是设置值把切换时间也都考虑进去了吧。
SK_SW1_INIT();
while (TRUE == SK_SW1_GET())
;
Gpio_InitIO(3, 4, GpioDirOut);
DDL_ZERO_STRUCT(stcCfg);
stcCfg.enClk = ClkRCH; // hclk/8=500k
stcCfg.u32LoadVal = 0xF9Fu; // 1ms(3999) ?手册写的如此,但是根据公式计算不出来
Clk_SysTickConfig(&stcCfg);
SysTick_Config(stcCfg.u32LoadVal);
中断中翻转GPIO,因为定时是1kHz,但是每次进入翻转,所以GPIO输出周期是500Hz。
以上是关于CMT2380F32模块开发5-CLK例程的主要内容,如果未能解决你的问题,请参考以下文章