• 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作为触发,否则以后就无法下载了。

    1. //外部SW1控制程序是否继续运行
    2. SK_SW1_INIT();
    3. while (TRUE == SK_SW1_GET())
    4. ;
    5. //设置P31为时钟输出IO
    6. Clk_SetFunc(ClkFuncSwdPinIOEn, TRUE);
    7. Gpio_SetFunc_HCLKOUT_P31();
    8. // CLK初始化
    9. DDL_ZERO_STRUCT(stcCfg);
    10. stcCfg.enClkSrc = ClkRCH;
    11. stcCfg.enHClkDiv = ClkDiv128;
    12. stcCfg.enPClkDiv = ClkDiv8;
    13. Clk_Init(&stcCfg);

    用示波器查看P31引脚,默认内部HCLK = 4M  示波器频率= 4M/128 = 32KHz。

    clk_div例程

    这个例程本来是对外部时钟分频的,由于模块没有外部时钟,所以这里改成了对内部时钟分频,就和clk_init一样了。

    clk_switch例程

    这个例程举例了时钟模块频率切换的过程,还是用示波器查看P31管脚,按下一次按键切换一次频率。

    1. // SW1控制程序是否继续运行
    2. SK_SW1_INIT();
    3. while (TRUE == SK_SW1_GET())
    4. ;
    5. //设置P31为HCLK输出
    6. Clk_SetFunc(ClkFuncSwdPinIOEn, TRUE);
    7. Gpio_SetFunc_HCLKOUT_P31();
    8. u32Val = Clk_GetHClkFreq();
    9. //系统时钟频率设置与切换
    10. // RCH 4MHz
    11. Clk_SwitchTo(ClkRCL);
    12. Clk_SetRCHFreq(ClkFreq4Mhz);
    13. Clk_SwitchTo(ClkRCH);
    14. u32Val = Clk_GetHClkFreq();
    15. while (TRUE == SK_SW1_GET())
    16. ;
    17. // RCH 8MHz
    18. Clk_SwitchTo(ClkRCL);
    19. Clk_SetRCHFreq(ClkFreq8Mhz);
    20. Clk_SwitchTo(ClkRCH);
    21. u32Val = Clk_GetHClkFreq();
    22. while (TRUE == SK_SW1_GET())
    23. ;
    24. // RCH 16MHz
    25. Clk_SwitchTo(ClkRCL);
    26. Clk_SetRCHFreq(ClkFreq16Mhz);
    27. Clk_SwitchTo(ClkRCH);
    28. u32Val = Clk_GetHClkFreq();
    29. while (TRUE == SK_SW1_GET())
    30. ;
    31. // RCH 22.12MHz
    32. Clk_SwitchTo(ClkRCL);
    33. Clk_SetRCHFreq(ClkFreq22_12Mhz);
    34. Clk_SwitchTo(ClkRCH);
    35. u32Val = Clk_GetHClkFreq();
    36. while (TRUE == SK_SW1_GET())
    37. ;
    38. // RCH 24MHz
    39. Clk_SwitchTo(ClkRCL);
    40. Clk_SetRCHFreq(ClkFreq24Mhz);
    41. Clk_SwitchTo(ClkRCH);
    42. u32Val = Clk_GetHClkFreq();
    43. while (TRUE == SK_SW1_GET())
    44. ;
    45. // RCL 38.4K
    46. Clk_SetRCLFreq(ClkFreq38_4K);
    47. Clk_SwitchTo(ClkRCL);
    48. u32Val = Clk_GetHClkFreq();
    49. while (TRUE == SK_SW1_GET())
    50. ;
    51. // RCL 32768
    52. Clk_SetRCLFreq(ClkFreq32768);
    53. u32Val = Clk_GetHClkFreq();
    54. while (TRUE == SK_SW1_GET())
    55. ;
    56. ///< \todo check 2nd version
    57. Clk_SwitchTo(ClkRCL);
    58. Clk_SetRCHFreq(ClkFreq4Mhz);
    59. Clk_SwitchTo(ClkRCH);
    60. u32Val = Clk_GetHClkFreq();

    clk_stb_time例程

    这个例程展示时钟模块的晶振稳定时间的设置方法,查看示波器,测量P34低电平时间是否大于设定的稳定时间。

    1. // SW1控制程序是否继续执行
    2. SK_SW1_INIT();
    3. while (TRUE == SK_SW1_GET())
    4. ;
    5. #if 1 // RCL
    6. // stable time
    7. Clk_SetRCL_StableTime(ClkCycle256);
    8. // enable new clock
    9. M0P_CLOCK->SYSCTRL2 = 0x5A5A;
    10. M0P_CLOCK->SYSCTRL2 = 0xA5A5;
    11. M0P_GPIO->P3OUT_f.P34 = 0;
    12. M0P_CLOCK->SYSCTRL0_f.RCL_EN = TRUE;
    13. // check stable
    14. while (FALSE == M0P_CLOCK->RCL_CR_f.STABLE)
    15. ;
    16. M0P_GPIO->P3OUT_f.P34 = 1;
    17. // switch new
    18. M0P_CLOCK->SYSCTRL2 = 0x5A5A;
    19. M0P_CLOCK->SYSCTRL2 = 0xA5A5;
    20. M0P_CLOCK->SYSCTRL0_f.CLK_SW4_SEL = ClkRCL;
    21. delay1ms(100);
    22. Clk_SwitchTo(ClkRCH);

    clk_systick例程

    处理器中有一个称为 SysTick 的简单定时器,用于产生周期性的中断请求。
    连接P34到示波器,查看P34频率是否为500Hz。
    这个部分有意思的是,文档给了不同时钟下的溢出周期设置值,《AN220-CMT2380F32用户指南(微控制器部分)-CN-V1.0-20200107》P322,但是根据公式却算不出来,可能是设置值把切换时间也都考虑进去了吧。

    1. SK_SW1_INIT();
    2. while (TRUE == SK_SW1_GET())
    3. ;
    4. Gpio_InitIO(3, 4, GpioDirOut);
    5. DDL_ZERO_STRUCT(stcCfg);
    6. stcCfg.enClk = ClkRCH; // hclk/8=500k
    7. stcCfg.u32LoadVal = 0xF9Fu; // 1ms(3999) ?手册写的如此,但是根据公式计算不出来
    8. Clk_SysTickConfig(&stcCfg);
    9. SysTick_Config(stcCfg.u32LoadVal);

    中断中翻转GPIO,因为定时是1kHz,但是每次进入翻转,所以GPIO输出周期是500Hz。

  • 相关阅读:
    46、TCP的“三次握手”
    Stearic acid-PEG-FITC 硬脂酸-聚乙二醇-荧光素
    docker入门加实战—从部署MySQL入门docker
    ABAP bgRFC
    《计算机视觉中的多视图几何》笔记(0)
    站库分离技术--反向代理技术-雷池云WAF-给自己搭建一个安全点的网站
    Linux Framebuffer驱动框架、接口实现和使用
    在Winform开发中,我们使用的几种下拉列表展示字典数据的方式
    json入参取特定分段值--mirth
    机器学习策略篇:详解为什么是ML策略?(Why ML Strategy?)
  • 原文地址:https://blog.csdn.net/andylauren/article/details/126115971