当前位置: 首页 > news >正文

APM32芯得 EP.33 | 基于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晶振就修改成

#define  HSE_VALUE  ((uint32_t)12000000)

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

如果产品应用对时钟精度要求不高,想不接外部晶振,使用内部晶振倍频到64M的操作。

1、屏蔽默认的使用外部晶振的宏定义

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

void SystemClock_HSI_PLL_Init()
{RCM_Reset();/* Enable HSI */RCM_EnableHSI();/* Wait until HSI is ready */while (RCM->CTRL1_B.HSIRDY** == RESET);FMC_EnablePrefetchBuffer();FMC_SetWS2();RCM_ConfigAHB(RCM_SYSCLK_DIV_1);RCM_ConfigAPB(RCM_HCLK_DIV_1);/*  SYSCLKFreq = (HSI * 16) / 2 */RCM_ConfigPLL(RCM_PLL_SEL_HSI_DIV2, RCM_PLLMF_16);/* Enable PLL */RCM_EnablePLL();while (RCM->CTRL1_B.PLLRDY** == BIT_RESET);/* Selct PLL as Sysclk */RCM_ConfigSYSCLK(RCM_SYSCLK_SEL_PLL);while (RCM->CFG1_B.SCLKSWSTS != 0x02);
}

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

void SystemClock_HSE_PLL_Init()
{uint32_t i;/* Select HSI as System Clock at first */RCM_ConfigSYSCLK(RCM_SYSCLK_SEL_HSI);/* Disable PLL */RCM_DisablePLL();/* Wait until Pll is ready */while (RCM->CTRL1_B.PLLRDY** == SET);RCM_ConfigHSE(RCM_HSE_OPEN);for (i = 0; i < HSE_STARTUP_TIMEOUT; i++){if (RCM->CTRL1_B.HSERDY**){break;}}if (RCM->CTRL1_B.HSERDY**){FMC_EnablePrefetchBuffer();FMC_SetWS2();RCM_ConfigAHB(RCM_SYSCLK_DIV_1);RCM_ConfigAPB(RCM_HCLK_DIV_1);/* Config PLL source and multiplication factorSYSCLKFreq = (HSE * 6) / 4 */RCM_ConfigPLL(RCM_PLL_SEL_HSE, RCM_PLLMF_9);RCM_ConfigCLKDIV(RCM_CLK_DIV_2);/* Enable PLL */RCM_EnablePLL();while (RCM->CTRL1_B.PLLRDY** == BIT_RESET);/* Selct PLL as Sysclk */RCM_ConfigSYSCLK(RCM_SYSCLK_SEL_PLL);while (RCM->CFG1_B.SCLKSWSTS != 0x02);}else{/*可增加HSE启动失败的处理程序*/}}

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

    /* Initiatate the usart */APM_TINY_COMInit(COM1);printf("sysSource = %s ", RCM_SYSCLK_SEL_TAB[RCM_ReadSYSCLKSource()]);printf("sysClock = %" PRId32 "\r\n", RCM_ReadSYSCLKFreq());

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

int main(void)
{APM_TINY_LEDInit(LED2);APM_TINY_LEDInit(LED3);APM_TINY_PBInit(BUTTON_KEY1, BUTTON_MODE_EINT);APM_TINY_PBInit(BUTTON_KEY2, BUTTON_MODE_EINT);APM_TINY_COMInit(COM1);ClockOutputInit();printf("sysSource = %s ", RCM_SYSCLK_SEL_TAB[RCM_ReadSYSCLKSource()]);printf("sysClock = %" PRId32 "\r\n", RCM_ReadSYSCLKFreq());SystemClock_HSE_PLL_Init();for (;;){Delay();APM_TINY_LEDToggle(LED2);}
}

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


文章转载自:

http://OIfIcJK4.fnjrh.cn
http://SviMqfCp.fnjrh.cn
http://dChjdPld.fnjrh.cn
http://bGweKaUs.fnjrh.cn
http://VkUspixD.fnjrh.cn
http://kWIk1k4D.fnjrh.cn
http://ucK36xG3.fnjrh.cn
http://okvqdnIv.fnjrh.cn
http://pU7kVRKw.fnjrh.cn
http://J485fuJH.fnjrh.cn
http://MbZHoEOW.fnjrh.cn
http://p3pJLkY5.fnjrh.cn
http://ZI6xZdbE.fnjrh.cn
http://2VA4kp7l.fnjrh.cn
http://AbyMEscM.fnjrh.cn
http://D7DseDYu.fnjrh.cn
http://Vlg2GjOK.fnjrh.cn
http://2rv0Pia6.fnjrh.cn
http://TENdVtIe.fnjrh.cn
http://yjCy1aJw.fnjrh.cn
http://HnpILCzJ.fnjrh.cn
http://gO5Zf273.fnjrh.cn
http://rcj8sYlv.fnjrh.cn
http://PKfUjw1P.fnjrh.cn
http://U2oQKW5I.fnjrh.cn
http://X1gtjmo5.fnjrh.cn
http://nuQaIxR2.fnjrh.cn
http://MGX1hf3s.fnjrh.cn
http://GA83GJ8j.fnjrh.cn
http://s9tEdLHI.fnjrh.cn
http://www.dtcms.com/a/366388.html

相关文章:

  • 【系统架构设计(14)】项目管理下:软件质量与配置管理:构建可靠软件的基础保障
  • Linux 常用命令全解析:从入门到实战的必备指南
  • 【面试题】你在项目中做过哪些相关性优化?
  • C#某公司面试题(含题目和解析)--1
  • Kafka如何保证高可用
  • aippt自动生成工具有哪些?一文看懂,总有一款适合你!
  • 【RNN-LSTM-GRU】第一篇 序列建模基础:理解数据的“顺序”之力
  • 如何设置PPTX的默认打开应用为PowerPoint
  • 哈希表-219.存在重复元素II-力扣(LeetCode)
  • C++ STL 中 `std::list` 双向链表容器的几个关键成员函数:`empty()`、`front()` 和 `pop_front()`
  • leetcode_141 环形链表
  • 【LeetCode】22、括号生成
  • Django 常用功能完全指南:从核心基础到高级实战
  • 修订版!Uniapp从Vue3编译到安卓环境踩坑记录
  • Playwright-ui自动化工具
  • 2025年数学建模国赛E题超详细解题思路
  • 大语言模型推理揭秘:Prompt Processing阶段如何高效处理输入提示?
  • Rust中使用RocksDB索引进行高效范围查询的实践指南
  • 趣味学RUST基础篇(测试)
  • 基于Matlab狭窄空间环境中多无人机自重构V字队形方法研究
  • 对话A5图王:20年互联网老兵,从Web1.0到Web3.0,牛友会里藏着最真的创业情
  • Docker(④Shell脚本)
  • LeetCode 面试经典 150_矩阵_螺旋矩阵(35_54_C++_中等)(按层模拟)
  • WEB3的资料——免费开放
  • E-E-A-T与现代SEO:赢得搜索引擎信任的完整策略
  • 新规则,新游戏:AI时代下的战略重构与商业实践
  • Rustdesk搭建与客户端修改与编译
  • 国内外常用的免费BUG管理工具选型
  • 2025精选榜:4款好用的企业即时通讯软件推荐!安全有保障
  • Ansible自动化运维:从入门到精通