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例程的主要内容,如果未能解决你的问题,请参考以下文章

CMT2380F32模块开发10-高级定时器例程

CMT2380F32模块开发10-高级定时器例程

CMT2380F32模块开发3-GPIO例程

CMT2380F32模块开发3-GPIO例程

CMT2380F32模块开发7-reset例程

CMT2380F32模块开发7-reset例程