#申请原创#[url=home.php?mod=space&uid=760190]@21小跑堂 @21小跑堂 @21小跑堂 [/url] 一、前言 这两年进口的MCU都缺货的紧,要不就是价格涨的太吓人,ST的低功耗L系列还能买到,但是L系列的SRAM都普遍比较小,之前的项目NXP的MCU断货了,只能找一下国产替代。找代理推荐了华大的MCU,说是目前国产里面做的比较好的了,目前这种情况,申请样品肯定没什么指望了,自己买吧。立创上倒是有货,直接下单,选择了HC32D391FEUA-TFN32TR这一款。 二、学习时钟树 搞到片子之后准备去官网下资料,发现这款没什么资料,咨询了一下原厂,说是这款就是HC32F460改了一下封装,内核都是一样的,好吧,那就当HC32F460来弄。 首先学习时钟树,搞清楚了才能知道MCU处于一个什么状态,外部时钟就不考虑了,直接选择内部时钟,时钟树如下图: 使用内部振荡器初始化函数如下: /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) //static { 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_USB stc_clk_upll_cfg_t stcUpllCfg; #endif MEM_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,最大 168MHz stcSysClkCfg.enExclkDiv = ClkSysclkDiv2; // 当前 64MHz,最大 84MHz stcSysClkCfg.enPclk0Div = ClkSysclkDiv1; // 当前 128MHz,最大 168MHz stcSysClkCfg.enPclk1Div = ClkSysclkDiv2; // 当前 64MHz,最大 84MHz stcSysClkCfg.enPclk2Div = ClkSysclkDiv4; // 当前 32MHz,最大 60MHz stcSysClkCfg.enPclk3Div = ClkSysclkDiv4; // 当前 32MHz,最大 42MHz stcSysClkCfg.enPclk4Div = ClkSysclkDiv2; // 当前 64MHz,最大 84MHz CLK_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 } 实际我调试时用到了MRC的8MHZ内部晶振,需要的同学可以参数上面的,是HRC倍频的初始化。 三、焊接最小系统,调试掉电模式功耗 在学习完时钟树后,就把之前画好的PCB打样,准备先做一个最小系统,使用内部时钟跑起来。 原理图部分: 打样回来之后,焊了一块最小系统,准备先验证一下功耗是否能到达要求。飞线部分是调试串口,在调试一个没用过的新MCU的时候串口是少不了的,相当于我们的眼睛去看MCU运行状态,哈哈。 焊一个最小系统,来调试功耗,把外围器件都不要来测试功耗,如果功耗不能满足的话,接下来的工作就不用搞了。 四、跑例程,实测功耗PD1模式6ua,PD3模式2ua 例程在下图位置, 直接跑官方的例程lpm_lpw,吐槽一下官方,唤醒的例程太少了,只有外部IO事件唤醒的例子,估计是给开发板上的按键做的,实际项目有可能没有按键,那就需要用定时器或者RTC的事件进行唤醒。 不过大家有之前ST的经验,应该弄起来快,我之前常用的是飞思卡尔,一言难尽了。只能上网搜资料,我到处找资料发现这个用掉电模式的人真不多。HC32F460去做掉电模式资料基本没有,几个论坛上找最后也不知道有没有人解决这个问题。之前都是用中断唤醒,事件唤醒没接触过。 后来找到别人的经验,事件唤醒掉电PowerDown模式, 1. RTC配置还是按中断进行配置,也就是满足中断就是触发事件 2. 触发事件就会唤醒MCU 3. 程序直接复位,重新从0开始执行 4. 不会进入RTC中断 5. 可以用Ret_SRAM保存数据,复位后数据不会丢 我在调试中厚着脸皮不停的问原厂FEA,人都挺好,基本上都帮忙回答了,哈哈。 PD1就差不多够用了,PD3的话手册上面是这样写的,不能保证Ret_SRAM的数据了。 希望对大家有点帮助。
|
最小系统板更准确的测量了小花单片机的低功耗模式下的电流消耗,对于需要使用小华单片机的朋友具有参考价值。