3. RA MCU时钟系统与FSP时钟配置
RA系列MCU的时钟系统是整个芯片的“心跳源”,它决定了CPU执行速度、外设通信波特率、定时器计数精度以及ADC采样时序。如果时钟配置错误,最典型的现象是串口乱码、定时器周期偏差、USB枚举失败,甚至程序根本无法启动。因此理解RA的时钟树结构,并掌握FSP配置器中时钟的设定方法,是RA开发中最基础也最关键的一环。
RA时钟树的基本结构
RA MCU的时钟源大致分为三类:外部时钟、内部时钟和PLL倍频时钟。以RA6M5为例,外部可接入主时钟晶振(Main Clock,通常8~24MHz)和子时钟晶振(Sub Clock,32.768kHz);内部则提供高速振荡器HOCO(如16MHz/20MHz)、中速振荡器MOCO(8MHz)和低速振荡器LOCO(32.768kHz)。这些时钟源经过选择器后,进入PLL电路进行倍频,再通过系统分频器(SCKDIVCR)产生各总线与外设所需的时钟。
RA的时钟域主要包括:
- ICLK:CPU和高速总线的时钟,通常最高可达200MHz(RA6M5)。
- PCLKA/PCLKB/PCLKC/PCLKD:外设总线时钟,分别供给不同外设组,频率可独立分频。
- FCLK:闪存接口时钟,通常与ICLK同源但需满足闪存访问时序。
- BCLK:外部总线时钟,用于CS/SDRAM等接口。
- UCLK:USB时钟,需精确为48MHz或24MHz。
- CANCLK、SPICLK、ADCLK等专用外设时钟。
这些时钟并非独立产生,而是从PLL输出或主时钟经过不同分频系数得到。分频系数由SCKDIVCR寄存器中的位域控制,FSP配置器会自动计算并生成对应的初始化代码。
FSP配置器中的时钟设定
在e² studio中新建RA项目后,打开FSP配置器的“Clocks”选项卡,可以看到完整的时钟树图形界面。配置顺序建议从时钟源开始,逐步向下:
- 选择主时钟源:在“Main Clock”区域设置晶振频率(如24MHz),并勾选“Main Clock Oscillator”使能。若使用外部晶振,还需设置驱动能力(Drive Level)和稳定等待时间。
- 配置PLL:在“PLL”区域设置倍频系数。FSP会根据输入频率自动计算VCO频率并提示是否在合法范围内。例如输入24MHz,选择×10,VCO输出240MHz,再经PLL分频器(÷1)得到240MHz。
- 设置系统分频:在“System Clocks”区域分别设置ICLK、PCLKA、PCLKB、PCLKC、PCLKD、FCLK、UCLK等的分频系数。FSP会实时显示各时钟的最终频率,并用颜色提示是否超限。
- 配置外设专用时钟:如CANCLK、SPICLK、ADCLK等,根据外设需求单独设置分频。
- 生成代码:点击“Generate Project Content”,FSP会自动生成
bsp_clock_cfg.c和bsp_clock_cfg.h,其中包含R_BSP_ClockInit()函数,在main()之前由启动代码调用。
bsp_clock_cfg.h中的宏定义,例如BSP_CFG_ICLK_DIV、BSP_CFG_PLL_MUL等。修改这些宏后重新生成代码即可,无需手动操作寄存器。
代码中切换时钟模式与验证
虽然FSP配置器已经生成了初始化代码,但在某些低功耗场景下,需要在运行时动态切换时钟。例如从PLL高速模式切换到HOCO中速模式以降低功耗。RA提供了R_CGC模块的API来完成这一操作。
以下示例演示如何将系统时钟从PLL切换到HOCO,并验证切换结果:
#include "hal_data.h"
void clock_switch_demo(void)
{
fsp_err_t err;
cgc_clock_t target_clock = CGC_CLOCK_HOCO;
/* 1. 启动HOCO并等待稳定 */
err = R_CGC_ClockStart(&g_cgc_ctrl, target_clock, NULL, NULL);
if (FSP_SUCCESS != err) { __BKPT(0); }
/* 2. 等待HOCO稳定标志置位 */
while (R_CGC_ClockCheck(&g_cgc_ctrl, target_clock) != FSP_SUCCESS) {
/* 等待 */
}
/* 3. 切换系统时钟源到HOCO */
err = R_CGC_SystemClockSet(&g_cgc_ctrl, target_clock,
CGC_CLOCK_DIV_1, /* ICLK分频 */
CGC_CLOCK_DIV_2, /* PCLKA分频 */
CGC_CLOCK_DIV_4, /* PCLKB分频 */
CGC_CLOCK_DIV_4); /* PCLKD分频 */
if (FSP_SUCCESS != err) { __BKPT(0); }
/* 4. 停止PLL以省电 */
R_CGC_ClockStop(&g_cgc_ctrl, CGC_CLOCK_PLL);
}
切换完成后,可以通过读取R_CGC_ClockSourceGet()确认当前时钟源,或通过R_CGC_SystemClockFreqGet()获取各时钟的实际频率。更直观的验证方式是将CLKOUT引脚配置为输出ICLK或PCLKA,用示波器测量频率。例如在FSP配置器的“Pin”选项卡中将P4_7设为CLKOUT,并在“Clocks”中设置CLKOUT输出源为ICLK,分频系数为1,则示波器应测得200MHz(若ICLK为200MHz)。
R_CGC_ClockStart()内部会等待稳定标志,但用户仍需在切换前调用R_CGC_ClockCheck()确认。
常见配置错误与排查
时钟配置错误往往表现为“程序能下载但跑不起来”或“外设工作异常”。以下是几个典型问题:
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 串口输出乱码 | PCLKB频率与波特率计算不匹配 | 检查FSP中SCI的时钟源选择,确认PCLKB实际频率 |
| 定时器周期偏差大 | ICLK分频系数错误或PLL未锁定 | 读取SCKDIVCR和PLLCR寄存器,用CLKOUT测量 |
| USB枚举失败 | UCLK不是精确48MHz | 检查PLL输出和UCLK分频,确保48MHz±0.25% |
| 程序下载后不运行 | ICLK超过闪存等待周期允许值 | 降低ICLK或增加闪存等待周期(FCKCR) |
实际工程中,建议在main()开头调用一次时钟频率打印函数,将ICLK、PCLKA、PCLKB、UCLK等频率通过串口输出,作为系统启动自检的一部分。这样一旦时钟配置有误,可以第一时间发现,而不是等到外设异常再去反查。
掌握RA时钟树的关键在于理解“源—倍频—分频—分配”这条链路,并善用FSP配置器的可视化界面和自动计算功能。运行时切换时钟时,严格遵循“启动目标时钟→等待稳定→切换源→关闭旧时钟”的顺序,就能安全地实现功耗与性能的平衡。