news 2026/5/5 19:03:56

[APM32E0] 基于APM32E030解读APM库的高速时钟配置

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[APM32E0] 基于APM32E030解读APM库的高速时钟配置

每一家MCU厂家的SDK写法和寄存器功能都有所不同,如果不熟悉的话就会配置错误,导致MCU运行不稳定。
接下来就已APM32E030的手册和SDK,解读下高速时钟的配置和相关注意事项。
实现了解MCU的高速时钟要先看下用户手册。
高速时钟源分内部时钟源和外部时钟源:
内部时钟源
内部时钟包含 HSICLK(高速内部时钟信号)和 LSICLK(低速内部时钟信号)。
HSICLK 时钟信号由内部 8MHz 的 RC 振荡器产生。不同芯片的 RC 振荡器频率不同,且同一颗芯片随着温度、电压的变化也会存在差异;每个芯片的 HSICLK 时钟频率在出厂前已经被厂家校准到 1%(25℃、VDD=VDDA=3.3V)
外部时钟源
外部时钟信号包括 HSECLK(高速外部时钟信号)和 LSECLK(低速外部时钟信号)。
外部的时钟源有两种:
⚫ 外部晶体/陶瓷谐振器(常规的无源晶振)
⚫ 用户外部时钟(有源晶振或者是其他芯片提供的时钟)


从E030的用户手册可以看出,E030的最大主频也就是SYSCLK最大是72Mhz。系统时钟源可以从HSECLK(外部时钟的时钟),PLLCLK(PLL的时钟)、HSICLK(内部8M时钟)这三个中来选择。
HSECLK的输入时钟范围是4~32Mhz,可通过PLL的分频器和倍频器配置成PLL最大72M主频。
HSICLK的时钟频率是8M,并且需要固定2分频到PLL的倍频器,最大16倍频,所以最大主频只能配到64Mhz.

系统时钟会再经过AHBPSC和APBPSC分频配置后到各外设。其中TMR的时钟需要注意,所有 TMRxCLK(定时器时钟)频率分配由硬件按以下 2 种情况自动设置:
⚫如果相应的 APB 预分频系数是 1,定时器的时钟频率与所在 APB 总线频率一致。
⚫否则,定时器的时钟频率被设为与其相连的 APB 总线频率的 2 倍

具体的寄存器在用户手册中,主要是时钟控制寄存器 1(RCM_CTRL1)和时钟配置寄存器 1(RCM_CFG1),具体功能可以查看用户手册。

除了RCM相关的寄存器,还有Flash的等待周期与预取使能与时钟相关需要注意。


理论部分主要就这些,更详细的建议查看用户手册,接下来是代码的相关部分。
芯片上电实现会运行到启动文件,初始化完中断向量表后会进入到SystemInit()函数进行默认的时钟初始化。


在SystemInit()函数中会复位时钟相关的寄存器,然后进入SystemClockConfig();进行默认的时钟初始化。


SystemClockConfig()会根据宏定义来进行时钟初始化。


SDK默认配置的是8M外部无源晶振,配置主频72M。


如果需要配置更低的主频,可以直接通过选择不同的宏定义来直接切换。

如果使用的外部高速晶振是其他频率,比如4M、12M、16M等,就不能直接修改宏定义来配置主频,还需要做如下修改。
1、将HSE_VALUE改成实际的晶振频率,例如使用12M晶振就修改成

复制
  1. #define HSE_VALUE ((uint32_t)12000000)




2、修改PLL倍频系数寄存器PLLMULCFG=4,对应数据手册可以看到是6倍频12M*6=72M



如果产品应用对时钟精度要求不高,想不接外部晶振,使用内部晶振倍频到64M的操作。
1、屏蔽默认的使用外部晶振的宏定义


2、编写如下使用内部晶振的时钟初始化函数,在main函数中调用

复制
  1. voidSystemClock_HSI_PLL_Init()
  2. {
  3. RCM_Reset();
  4. /* Enable HSI */
  5. RCM_EnableHSI();
  6. /* Wait until HSI is ready */
  7. while(RCM->CTRL1_B.HSIRDY** == RESET);
  8. FMC_EnablePrefetchBuffer();
  9. FMC_SetWS2();
  10. RCM_ConfigAHB(RCM_SYSCLK_DIV_1);
  11. RCM_ConfigAPB(RCM_HCLK_DIV_1);
  12. /* SYSCLKFreq = (HSI * 16) / 2 */
  13. RCM_ConfigPLL(RCM_PLL_SEL_HSI_DIV2, RCM_PLLMF_16);
  14. /* Enable PLL */
  15. RCM_EnablePLL();
  16. while(RCM->CTRL1_B.PLLRDY** == BIT_RESET);
  17. /* Selct PLL as Sysclk */
  18. RCM_ConfigSYSCLK(RCM_SYSCLK_SEL_PLL);
  19. while(RCM->CFG1_B.SCLKSWSTS !=0x02);
  20. }

如果想要在程序运行中切换主频频率,比如将外部晶振72M的配置切换到36M

复制
  1. voidSystemClock_HSE_PLL_Init()
  2. {
  3. uint32_t i;
  4. /* Select HSI as System Clock at first */
  5. RCM_ConfigSYSCLK(RCM_SYSCLK_SEL_HSI);
  6. /* Disable PLL */
  7. RCM_DisablePLL();
  8. /* Wait until Pll is ready */
  9. while(RCM->CTRL1_B.PLLRDY** == SET);
  10. RCM_ConfigHSE(RCM_HSE_OPEN);
  11. for(i =0; i < HSE_STARTUP_TIMEOUT; i++)
  12. {
  13. if(RCM->CTRL1_B.HSERDY**)
  14. {
  15. break;
  16. }
  17. }
  18. if(RCM->CTRL1_B.HSERDY**)
  19. {
  20. FMC_EnablePrefetchBuffer();
  21. FMC_SetWS2();
  22. RCM_ConfigAHB(RCM_SYSCLK_DIV_1);
  23. RCM_ConfigAPB(RCM_HCLK_DIV_1);
  24. /* Config PLL source and multiplication factor
  25. SYSCLKFreq = (HSE * 6) / 4 */
  26. RCM_ConfigPLL(RCM_PLL_SEL_HSE, RCM_PLLMF_9);
  27. RCM_ConfigCLKDIV(RCM_CLK_DIV_2);
  28. /* Enable PLL */
  29. RCM_EnablePLL();
  30. while(RCM->CTRL1_B.PLLRDY** == BIT_RESET);
  31. /* Selct PLL as Sysclk */
  32. RCM_ConfigSYSCLK(RCM_SYSCLK_SEL_PLL);
  33. while(RCM->CFG1_B.SCLKSWSTS !=0x02);
  34. }
  35. else
  36. {
  37. /*可增加HSE启动失败的处理程序*/
  38. }
  39. }

如果要知道系统现在的时钟配置是多少,可以参考SDK中的RCB-->RCM_ClockSwitch 例程

复制
  1. /* Initiatate the usart */
  2. APM_TINY_COMInit(COM1);
  3. printf("sysSource = %s ", RCM_SYSCLK_SEL_TAB[RCM_ReadSYSCLKSource()]);
  4. printf("sysClock = %"PRId32"\r\n", RCM_ReadSYSCLKFreq());

使用串口来打印当前时钟配置,注意这个打印是基于HSE_VALUE与实际相符的情况才是准确的,需要注意核对。

复制
  1. intmain(void)
  2. {
  3. APM_TINY_LEDInit(LED2);
  4. APM_TINY_LEDInit(LED3);
  5. APM_TINY_PBInit(BUTTON_KEY1, BUTTON_MODE_EINT);
  6. APM_TINY_PBInit(BUTTON_KEY2, BUTTON_MODE_EINT);
  7. APM_TINY_COMInit(COM1);
  8. ClockOutputInit();
  9. printf("sysSource = %s ", RCM_SYSCLK_SEL_TAB[RCM_ReadSYSCLKSource()]);
  10. printf("sysClock = %"PRId32"\r\n", RCM_ReadSYSCLKFreq());
  11. SystemClock_HSE_PLL_Init();
  12. for(;;)
  13. {
  14. Delay();
  15. APM_TINY_LEDToggle(LED2);
  16. }
  17. }


这是启动文件不初始化时钟,在main中配置64M主频的测试结果


---------------------
作者:Alden
链接:https://bbs.21ic.com/icview-3459364-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 1:08:02

研究生必备!9个免费AI论文工具,开题报告一键搞定

如果你正在熬夜赶Deadline的毕业生、被导师连环催促却毫无头绪的研究生、或者囊中羞涩却要面对知网查重天价账单的大学生…… 请停一停&#xff0c;这篇文章就是为你量身定制的。 想象一下——凌晨两点的宿舍&#xff0c;电脑屏幕泛着冷光&#xff0c;Word文档依旧只有孤零零的…

作者头像 李华
网站建设 2026/5/3 10:10:02

FaceFusion能否实现动物脸替换?猫狗换脸实验

FaceFusion能否实现动物脸替换&#xff1f;猫狗换脸实验 在短视频平台上&#xff0c;“萌宠变装”特效正变得越来越流行&#xff1a;一只橘猫突然长出柯基的短腿&#xff0c;金毛犬眨着布偶猫的大眼睛卖萌……这些看似轻松有趣的视觉效果背后&#xff0c;其实隐藏着一个极具挑…

作者头像 李华
网站建设 2026/5/1 7:15:32

FaceFusion如何设置GPU利用率阈值预警?

FaceFusion如何设置GPU利用率阈值预警&#xff1f; 在深度学习驱动的图像处理应用中&#xff0c;人脸融合技术正变得越来越普及。像 FaceFusion 这样的工具&#xff0c;凭借其强大的换脸能力&#xff0c;在视频创作、虚拟偶像生成和娱乐内容生产等领域大放异彩。但随之而来的…

作者头像 李华
网站建设 2026/4/25 10:27:36

FaceFusion如何处理刘海遮挡眉毛时的表情迁移?

FaceFusion如何处理刘海遮挡眉毛时的表情迁移&#xff1f; 在虚拟主播直播正酣、数字人内容爆发的今天&#xff0c;一个看似微不足道的技术细节——“齐刘海下那条看不见的眉毛”——却可能成为压垮整段表情迁移效果的最后一根稻草。观众或许说不清哪里不对&#xff0c;但只要眉…

作者头像 李华
网站建设 2026/5/4 14:30:56

Langchain-Chatchat与Telegraf监控代理集成采集指标

Langchain-Chatchat 与 Telegraf 集成&#xff1a;构建安全可控的智能问答可观测体系 在企业知识管理日益复杂的今天&#xff0c;一个常见的困境是&#xff1a;公司内部积累了大量 PDF、Word 和 PPT 形式的制度文档、产品手册和技术规范&#xff0c;但员工却常常“知道有资料&a…

作者头像 李华
网站建设 2026/4/28 8:30:51

24、探索 Linux:游戏与命令行的精彩世界

探索 Linux:游戏与命令行的精彩世界 1. Linux 游戏的多样魅力 Linux 系统中有着丰富多样的游戏,为用户带来了别样的娱乐体验。 1.1 Kolf:虚拟高尔夫之旅 Kolf 是 KDE 界面下的一款电脑高尔夫游戏,即便不喜欢在真实球场上打高尔夫的人,也能在其中找到放松的乐趣。启动新…

作者头像 李华