今天在新项目(MCU 为华大 HC32F460)中不再使用外部晶振,转而要使用 HC32F460 内部的 HRC,之前在使用外部晶振时,对华大 MCU 的时钟配置有过一些了解,但是,由于使用内部晶振与使用外部晶振有些差别,今天就记录一下配置过程!没啥难的,就是单纯记录一下而已!

  华大 MCU 时钟的配置,与 ST 的类似,都有很多选择,用户可以根据需要灵活选择。用户手册章节 6 时钟控制器(CMU)中的介绍已经很详细了,所以本文就重点结合代码来说明,还有就是从手册中摘录了一些配置中需要重点关注的点。

时钟控制器(CMU)

  系统时钟框图是个好东西,基本配置项都一目了然了!如下图所示,左侧就是可选的时钟源。XTAL 就类似于 ST 的 HSE;XTAL32 就类似于 ST 的 LSE;HRC 就类似于 ST 的 HSI;LRC 就类似于 ST 的 LSI,至于 MRC 和 SWDTLRC 与 ST 差别就要大一些了。

  • 外部高速振荡器(XTAL) 晶振的频率范围:4~24MHz
  • 外部低速振荡器(XTAL32) 晶振的频率范围:32.768KHz
  • MPLL 时钟(MPLL) 输入时钟输入可选外部高速振荡器(XTAL)或者内部高速振荡器(HRC)
  • UPLL 时钟(UPLL) 输入时钟:输入可选外部高速振荡器(XTAL)或者内部高速振荡器(HRC)
  • 内部高速振荡器(HRC) 频率:16MHz 或者20MHz
  • 内部中速振荡器(MRC) 频率:8MHz
  • 内部低速振荡器(LRC) 频率:32.768KHz
  • SWDT 专用内部低速振荡器(SWDTRC)频率:10KHz

HRC

  HRC 的频率可由 ICG1. HRCFREQSEL 配置成 16MHz 或者 20MHz。HRC 振荡器的优点是成本较低(无需使用外部组件)。此外,其启动速度也要比 XTAL 晶振块,但即使校准后,其精度也不及外部晶振。我本次要使用 HRC,所以本文就以 HRC 为重点关注对象,其他时钟的配置基本类似。

  其中,需要重点关注 ICG 这个部分。用户手册章节 8 初始化配置(ICG)中有详细描述,这一部分貌似和 ST 的 OPT FLASH(或者叫 Option bytes)的作用差不多。重点关注的原因就是这个部分不是读写寄存器操作,而是在编写代码时,直接固化数据(通常使用编译器指令),下面是华大给出的库中的处理代码(hc32f46x_icg.c):

#if defined ( __GNUC__ ) && !defined (__CC_ARM) /* GNU Compiler */
const uint32_t u32ICG[] __attribute__((section(".icg_sec"))) =
#elif defined (__CC_ARM)
const uint32_t u32ICG[] __attribute__((at(0x400))) =
#elif defined (__ICCARM__)
__root const uint32_t u32ICG[] @ 0x400 =
#else
#error "unsupported compiler!!"
#endif
{/* ICG 0~ 3 */ICG0_REGISTER_CONSTANT,ICG1_REGISTER_CONSTANT,ICG2_REGISTER_CONSTANT,ICG3_REGISTER_CONSTANT,/* ICG 4~ 7 */ICG4_REGISTER_CONSTANT,ICG5_REGISTER_CONSTANT,ICG6_REGISTER_CONSTANT,ICG7_REGISTER_CONSTANT,
};

  其中,uint32_t u32ICG[] 这个数组中就是使用编译器命令固化的数据。里面的这些宏值的配置,不得不库文件 hc32f46x_icg.h 中根据需要来修改!这里要发句牢骚,对于 hc32f46x_icg.hddl_config.h 有毛用! 看我下面的需求:

有些宏值的配置无法放到 ddl_config.h 中,不得不更改库文件!然后在配置时钟时需要使用如下代码:

    /* 1. 启动 HRC, MCU 启动后默认以 MRC 来工作,以下开始切换到 HRC */CLK_HrcCmd(Enable);/* 根据手册,需要等待 HRC Ready 后才可以正常使用 */while(Set != CLK_GetFlagStatus(ClkFlagHRCRdy));

  这里有个坑需要注意,我之前在博文《华大 MCU 之一 HC32F460 替换 STM32F411 移植记录 》中也有说过。实际项目中,我们的程序结构多为下图所示:

hc32f46x_icg.c 只能放在 IAP 中!如果放到了 APP 中编译会产生错误!例如,在 ST 中,我们通常会在 APP 中来配置看门狗,但是在华大中这就行不通了!

PLL 的配置

  在实际使用中,我们多数情况下需要将时钟源进行倍频,以使系统时钟达到一个较高的频率。倍频使用的器件就是 PLL。HC32F46xx 器件具有两个PLL:

  • MPLL 由 XTAL 或HRC 振荡器提供时钟信号,并具有三个不同的输出时钟:

    • P 分频器输出用于生成系统时钟(最高达 200 MHz)
    • 三个输出都可用于生成 USBFS、TRNG、ADC 和 I2S 时钟。
  • UPLL 三个输出亦可用于生成 USBFS、TRNG、ADC 和 I2S 时钟。

使用时注意以下三点:

  1. 在 HRC 或 XTAL 振荡器稳定后,再对 PLL 进行配置。
  2. MPLL/UPLL 的分频系数 M、N、P、Q、R 可独立配置(系统时钟框图中 N 在哪?我也不知道!)。由于在 PLL 使能后 PLL 配置参数便不可更改,所以建议先对 PLL 进行配置,然后再使能。
  3. 当进入掉电和停止模式后,两个 PLL 将由硬件禁止。

基本就是对应下面的代码(这里只配置了 MPLL,文章最后的完整示例里有 UPLL的配置)了:

    /* 2. 设置 PLL 的时钟源为 HRC */CLK_SetPllSource(ClkPllSrcHRC);/* 3. MPLL config (主晶振 / pllmDiv * plln / PllpDiv = 128M). */stcMpllCfg.pllmDiv = 16ul;stcMpllCfg.plln    = 256ul;stcMpllCfg.PllpDiv = 2ul;stcMpllCfg.PllqDiv = 8ul;stcMpllCfg.PllrDiv = 2ul;CLK_MpllConfig(&stcMpllCfg);/* Enable MPLL. */CLK_MpllCmd(Enable);

各种外设时钟

  时钟的配置还有一部分就是分频出各种外设时钟(系统时钟框图的右侧输出的各种时钟),分频出各种外设时钟没有啥难的,只要保证不超过限制即可。各时钟的说明如下:

基本就是对应下面的代码(具体的分配系数根据自己的需求变化):

    /* Set bus clk div. */stcSysClkCfg.enHclkDiv = ClkSysclkDiv1;   // 当前 128MHz,最大 168MHzstcSysClkCfg.enExclkDiv = ClkSysclkDiv2;  // 当前 64MHz,最大 84MHzstcSysClkCfg.enPclk0Div = ClkSysclkDiv1;  // 当前 128MHz,最大 168MHzstcSysClkCfg.enPclk1Div = ClkSysclkDiv2;  // 当前 64MHz,最大 84MHzstcSysClkCfg.enPclk2Div = ClkSysclkDiv4;  // 当前 32MHz,最大 60MHzstcSysClkCfg.enPclk3Div = ClkSysclkDiv4;  // 当前 32MHz,最大 42MHzstcSysClkCfg.enPclk4Div = ClkSysclkDiv2;  // 当前 64MHz,最大 84MHzCLK_SysClkConfig(&stcSysClkCfg);

时钟切换

  无论是华大还是 ST,都有一个章节来专门介绍时钟的切换。在系统启动以及进出低功耗时,都有可能需要进行时钟切换,如果没有正常的切换,可能导致无法启动。时钟切换必须严格遵循手册中给出的切换步骤!

  在系统复位后,默认系统时钟为 MRC。通过设定寄存器 CMU_CKSW 切换时钟源,切换步骤参照时钟源切换。只有在目标时钟源已稳定的状态下,才可以从一个时钟源切换到另一个时钟源。

  时钟切换时需要正确配置 Flash/SRAM 的等待周期,防止系统时钟频率大于 Flash/SRAM 的最大动作频率。这个也是很重要的,用惯了 ST 标准库的人可能对这个部分比较陌生,因为 ST 的工具会根据我们配置的频率自动为我们生成这部分的处理,手动移植时,就必须要关注这部分的配置。Flash/SRAM 的等待周期如下图所示:

关于这部分在用户手册 CPU 时钟和 FLASH 读取时间之间的关系 中有详细的步骤描述。

最终配置

最终,一个完整的配置时钟的函数如下所示:

/*** @brief System Clock Configuration* @retval None*/
static void SystemClock_Config(void)
{stc_clk_sysclk_cfg_t        stcSysClkCfg;// stc_clk_xtal_cfg_t          stcXtalCfg;      /* 配置外部 Xtal */// stc_clk_xtal32_cfg_t        stcXtal32Cfg;      /* 配置外部 Xtal32 */stc_clk_mpll_cfg_t          stcMpllCfg;stc_sram_config_t           stcSramConfig;#ifdef USE_USBstc_clk_upll_cfg_t          stcUpllCfg;#endifMEM_ZERO_STRUCT(stcSysClkCfg);// MEM_ZERO_STRUCT(stcXtalCfg);// MEM_ZERO_STRUCT(stcXtal32Cfg);MEM_ZERO_STRUCT(stcMpllCfg);MEM_ZERO_STRUCT(stcSramConfig);/* Set bus clk div. */stcSysClkCfg.enHclkDiv = ClkSysclkDiv1;   // 当前 128MHz,最大 168MHzstcSysClkCfg.enExclkDiv = ClkSysclkDiv2;  // 当前 64MHz,最大 84MHzstcSysClkCfg.enPclk0Div = ClkSysclkDiv1;  // 当前 128MHz,最大 168MHzstcSysClkCfg.enPclk1Div = ClkSysclkDiv2;  // 当前 64MHz,最大 84MHzstcSysClkCfg.enPclk2Div = ClkSysclkDiv4;  // 当前 32MHz,最大 60MHzstcSysClkCfg.enPclk3Div = ClkSysclkDiv4;  // 当前 32MHz,最大 42MHzstcSysClkCfg.enPclk4Div = ClkSysclkDiv2;  // 当前 64MHz,最大 84MHzCLK_SysClkConfig(&stcSysClkCfg);// /* XTAL的配置 */// /* Use Xtal as MPLL source. */// stcXtalCfg.enMode        = ClkXtalModeOsc;// stcXtalCfg.enDrv         = ClkXtalMidDrv;// stcXtalCfg.enFastStartup = Enable;// CLK_XtalConfig(&stcXtalCfg);// CLK_XtalCmd(Enable);/* 配置 HRC 经过 PLL 后作为系统时钟,而不是直接使用 HRC(HRC 是可以直接作为系统时钟) *//* 1. 启动 HRC, MCU 启动后默认以 MRC 来工作,以下开始切换到 HRC */CLK_HrcCmd(Enable);/* 根据手册,需要等待 HRC Ready 后才可以正常使用 */while(Set != CLK_GetFlagStatus(ClkFlagHRCRdy));/* 2. 设置 PLL 的时钟源为 HRC */CLK_SetPllSource(ClkPllSrcHRC);/* 3. MPLL config (主晶振 / pllmDiv * plln / PllpDiv = 128M). */stcMpllCfg.pllmDiv = 16ul;stcMpllCfg.plln    = 256ul;stcMpllCfg.PllpDiv = 2ul;stcMpllCfg.PllqDiv = 8ul;stcMpllCfg.PllrDiv = 2ul;CLK_MpllConfig(&stcMpllCfg);/* Enable MPLL. */CLK_MpllCmd(Enable);/* flash read wait cycle setting */EFM_Unlock();EFM_SetLatency(EFM_LATENCY_3);EFM_Lock();/* sram init include read/write wait cycle setting */stcSramConfig.u8SramIdx = Sram12Idx | Sram3Idx | SramHsIdx | SramRetIdx;stcSramConfig.enSramRC = SramCycle2;stcSramConfig.enSramWC = SramCycle2;stcSramConfig.enSramEccMode = EccMode3;stcSramConfig.enSramEccOp = SramNmi;stcSramConfig.enSramPyOp = SramNmi;SRAM_Init(&stcSramConfig);/* Wait MPLL ready. */while(Set != CLK_GetFlagStatus(ClkFlagMPLLRdy));/* Switch system clock source to MPLL. */CLK_SetSysClkSource(CLKSysSrcMPLL);#if (DDL_RTC_ENABLE == DDL_ON)// CLK_LrcCmd(Enable);     //Enable LRC   for RTC// /* RTC 用 xtal32 */// stcXtal32Cfg.enFastStartup = Disable;// stcXtal32Cfg.enDrv = ClkXtal32HighDrv;// stcXtal32Cfg.enFilterMode = ClkXtal32FilterModeFull;// CLK_Xtal32Config(&stcXtal32Cfg);// /* Startup xtal32 */// CLK_Xtal32Cmd(Enable);// /* wait for xtal32 running */// Ddl_Delay1ms(3000u);#endif#if DDL_USBFS_ENABLE == DDL_ON/* UPLL config (XTAL(当前为 6M) / pllmDiv * plln / PllpDiv = 48M). */stcUpllCfg.pllmDiv = 6u;stcUpllCfg.plln = 48u;stcUpllCfg.PllpDiv = 1u;//48MstcUpllCfg.PllqDiv = 1u;stcUpllCfg.PllrDiv = 1u;CLK_UpllConfig(&stcUpllCfg);CLK_UpllCmd(Enable);/* Wait UPLL ready. */while(Set != CLK_GetFlagStatus(ClkFlagUPLLRdy)){;}/* Set USB clock source */CLK_SetUsbClkSource(ClkUsbSrcUpllp);#endif
}

参考

  1. HC32F460系列用户手册Rev1.2.pdf

华大 MCU 之三 时钟控制器(CMU)配置记录相关推荐

  1. 华大 MCU 之一 HC32F460 替换 STM32F411 移植记录

    更新 2020年 10 月 21 日,将驱动库更新到了最新版 1.1.1 2020年 10 月 20 日,MCU 由原来的 HC32F460KCTA 更换为 HC32F460KETA 简介   目前, ...

  2. 华大 MCU 之七 DMA 导致 SPI 异常停止的原因分析、DMA 配置的那些坑

    缘起   在最近的项目测试中发现,SPI 通信总是莫名其妙的失败,查看寄存器发现 SPI 已经被停止了.根据手册,SPI 在异常情况下会被强制停止(SPI 的使能为被清零),而根据波形显示通信过程没有 ...

  3. 华大 MCU 之四 使用问题记录

      在最近使用华大 MCU 时,遇到了不少坑,这里记录一下,以方便在以后升级驱动库!其中,有些问题仅仅是在由 ST 切换到 华大之后不太适于的问题,有些是驱动库的更改问题!   如果您发现我说的问题是 ...

  4. 华大 MCU 之五 SPI 从机 DMA 模式 配置(不能正常接收问题处理)

      最近有个需求是需要使用 华大 MCU(HC32F460) 的 SPI 作为从机来接收数据,无奈搞了两天死活不可用.配置完 SPI 的从机模式后,只要启动主机端的发送就出现如下图所示的错误: 下面是 ...

  5. MCAL-GTM之时钟管理CMU

    文章目录 前言 时钟管理单元CMU CMU时钟图 GTM全局时钟分频 Cmu CFGU时钟分配 产生的时钟示例图: Cmu FXU时钟分配 Cmu EGU时钟分配 总结 前言 项目需要配置PWM信号采 ...

  6. 活动目录系列之三---域控制器常规卸域

    活动目录系列之三---域控制器常规卸域 在介绍正题之前,先补充很多人提出的一个疑问,就是什么情况下计算机名系统不让更改,其实很简单,当在域情况下,用非管理员登陆域,即计算机名就不让更改,运行---CM ...

  7. 华大 MCU 之六 SEGGER Embedded Studio 及 Ozone 使用 Jlink 调试

      首先说一下,我之前的开发流程是:VSCode 编辑代码 + Keil 编译及调试.Keil 的调试功能虽然很强大,但是多数功能需要配合 ARM 自家的 ULINKpro 才可以用,例如 Perfo ...

  8. 华大单片机HC32L130/HC32L136红外端口配置

    华大单片机HC32L130/HC32L136红外端口配置 HC32L130一共有三个引脚可以配置成红外38.4KHZ输出引脚 #define PIN_PWM_IR GpioPortB, GpioPin ...

  9. MCU集成-时钟复位控制

    时钟 首先我们需要知道我们生成时钟的需求如下. 然后知道设计要点 dft可控:表示在dft模式下,我们选择外部的测试时钟而不是芯片内部的pll的时钟.这个外部的时钟可以被dft工程师控制. dft隔离 ...

最新文章

  1. 用python的matplotlib画标准正态曲线
  2. uniapp中实现每次点击左侧菜单右边区域都从顶部开始
  3. 【工具】PC端调试手机端 Html 页面的工具
  4. C++知识总结(2)--字符串和数组
  5. 9.3 LSMW程序创建操作手册 第5 6 7步
  6. 首次!阿里达摩院将Pure Transformer 应用于目标重识别ReID!
  7. 在 eclipse 中设置每行的字数
  8. 南邮计算机科学与技术专业排名,南京邮电大学王牌专业有哪些
  9. sigmoid 激励函数
  10. 金蝶EAS,序时簿ListUI只允许选择一行或至少选择一行记录
  11. 数据挖掘:数据(数据的基本统计描述)
  12. A reference for learning process
  13. Centos 通过 Nginx 和 vsftpd 构建图片服务器
  14. 无心剑中译狄兰·托马斯《不要温顺地走进那个良夜》
  15. 关于科技将如何塑造旅行和流动性的七个预测
  16. 如何进行支付功能的测试
  17. Unity5新版Shader模板源码解析
  18. 小程序canvas画画板签字版,touchmove时卡顿的问题(根本原因是因为vue语法中page.data导致视图层和逻辑层的频繁通讯导致)
  19. pluseaudio 的设置声卡
  20. Linux ALSA声卡驱动之七:录音(Capture) 调用流程

热门文章

  1. 阿里云朱照远:AI打开新视界 8K时代已来!
  2. 直接让浏览器下载文件而不打开
  3. 【C++学习】String类的基本用法
  4. SQL Server 2000从入门到精通3
  5. 推荐 7 个 Github 上近 200k Star 的计算机学习资源,练好前端内功的秘籍!
  6. 2:IDEA生成springboot项目,修改启动图标和网页端口
  7. SpringBatch批处理框架入门(一)
  8. vue elementui el-select通过@Change触发事件
  9. lombok pom.xml依赖
  10. golang管道channel的遍历和关闭:应该使用for...range来遍历