概述
nRF52805 是 Nordic 推出的低功耗蓝牙 SoC,其时钟系统设计为满足低功耗和高性能的平衡需求。以下是详细的时钟配置功能介绍:
1. 时钟系统架构
nRF52805 包含以下主要时钟源:
1.1 高频时钟 (HFCLK)
- 时钟源 :
- 内部 64 MHz RC 振荡器 (HFRC)
- 外部 32 MHz 晶振 (HFXO)
- 用途 :
- CPU 运行
- 高速外设(如 SPI、UART 等)
- 蓝牙射频
1.2 低频时钟 (LFCLK)
- 时钟源 :
- 内部 32.768 kHz RC 振荡器 (LFRC)
- 外部 32.768 kHz 晶振 (LFXO)
- 由 HFCLK 合成的 32.768 kHz 时钟 (SYNTH)
- 用途 :
- 低功耗模式下的定时器和计数器
- RTC(实时时钟)
- 蓝牙协议栈定时
2. 时钟配置寄存器
2.1 高频时钟配置
- NRF_CLOCK->TASKS_HFCLKSTART:启动 HFCLK
- NRF_CLOCK->TASKS_HFCLKSTOP:停止 HFCLK
- NRF_CLOCK->EVENTS_HFCLKSTARTED:HFCLK 启动完成事件
- NRF_CLOCK->HFCLKSRC:选择 HFCLK 源(内部 RC 或外部晶振)
2.2 低频时钟配置
- NRF_CLOCK->TASKS_LFCLKSTART:启动 LFCLK
- NRF_CLOCK->TASKS_LFCLKSTOP:停止 LFCLK
- NRF_CLOCK->EVENTS_LFCLKSTARTED:LFCLK 启动完成事件
- NRF_CLOCK->LFCLKSRC:选择 LFCLK 源(RC、Xtal 或 Synth)
3. 时钟源选择依据
3.1 高频时钟源选择
| 时钟源 | 精度 | 功耗 | 启动时间 | 适用场景 |
|---|---|---|---|---|
| 内部 RC (HFRC) | ±1% | 低 | 快(~10μs) | 快速启动、低功耗应用 |
| 外部晶振 (HFXO) | ±20ppm | 高 | 慢(~1ms) | 高精度要求、蓝牙通信 |
3.2 低频时钟源选择
| 时钟源 | 精度 | 功耗 | 启动时间 | 适用场景 |
|---|---|---|---|---|
| 内部 RC (LFRC) | ±500ppm | 最低 | 快 | 超低功耗应用 |
| 外部晶振 (LFXO) | ±20ppm | 中 | 慢(~300ms) | 高精度定时、蓝牙协议栈 |
| 合成时钟 (SYNTH) | 与 HFCLK 相同 | 高 | 快 | HFCLK 已运行时 |
4. 代码配置示例
4.1 启动高频时钟(使用内部 RC)
c
// 启动 HFCLK 并等待启动完成
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK->TASKS_HFCLKSTART = 1;
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
4.2 配置低频时钟(使用内部 RC)
c
// 选择 LFCLK 源为内部 RC
NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_RC << CLOCK_LFCLKSRC_SRC_Pos);
// 启动 LFCLK
NRF_CLOCK->TASKS_LFCLKSTART = 1;
4.3 进入低功耗模式时的时钟配置
c
void power_control(void)
{
// 启用 DC/DC 转换器降低功耗
NRF_POWER->DCDCEN = 1;
// 配置电源监测
NRF_POWER->INTENSET = POWER_INTENSET_POFWARN_Msk;
NRF_POWER->POFCON = (POWER_POFCON_THRESHOLD_V27 << POWER_POFCON_THRESHOLD_Pos);
// 停止不需要的 HFCLK
NRF_CLOCK->TASKS_HFCLKSTOP = 1;
// 启动 LFCLK(使用内部 RC 以降低功耗)
NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_RC << CLOCK_LFCLKSRC_SRC_Pos);
NRF_CLOCK->TASKS_LFCLKSTART = 1;
// 进入低功耗模式
NRF_POWER->TASKS_LOWPWR = 1;
}
5. Zephyr RTOS 中的时钟配置
在 Zephyr RTOS 中,可以通过以下方式配置时钟:
5.1 设备树配置
在 boards 目录下的设备树文件中配置时钟源:
dts
&clock {
compatible = "nordic,nrf-clock";
status = "okay";
/* 配置 LFCLK 源为外部晶振 */
lfclk-source = <NRF_CLOCK_LFCLK_XTAL>;
};
5.2 Kconfig 配置
在 prj.conf 文件中添加配置:
# 启用外部 32.768 kHz 晶振
CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
# 启用外部 32 MHz 晶振
CONFIG_CLOCK_CONTROL_NRF_HFXO=y
5.3 低功耗优化建议
-
根据应用场景选择合适的时钟源:
- 蓝牙通信时使用外部晶振(LFXO)保证精度
- 非通信期间使用内部 RC(LFRC)降低功耗
-
动态时钟管理:
- 仅在需要时启动 HFCLK
- 完成任务后及时停止 HFCLK
-
合理配置时钟启动时间:
- 预留足够的启动时间,特别是外部晶振
-
使用 DC/DC 转换器:
- 启用 DC/DC 转换器可显著降低功耗
7. 注意事项
-
蓝牙协议要求:
- 蓝牙通信需要高精度时钟,通常建议使用外部晶振(LFXO)
-
温度影响:
- 内部 RC 振荡器受温度影响较大,温度变化时精度会降低
-
启动时间:
- 外部晶振启动时间较长,需要在代码中预留足够的等待时间
-
功耗平衡:
- 高精度时钟通常意味着更高的功耗,需要在精度和功耗之间找到平衡点
通过合理配置 nRF52805 的时钟系统,可以在保证应用性能的同时实现最低功耗,延长设备电池寿命。
7 退出低功耗模式时的时钟配置
当从低功耗模式恢复时,需要重新配置时钟系统以确保所有外设正常工作。以下是nRF52805退出低功耗模式时的时钟配置步骤:
7.1.基本配置步骤
7.1.1 启动高频时钟 (HFCLK)
c
// 启动 HFCLK 并等待启动完成
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK->TASKS_HFCLKSTART = 1;
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
7.1.2 重新初始化外设时钟
c
// 重新初始化 I2C
drv_i2c_init();
// 重新初始化 ADC
drv_adc_init();
// 重新初始化 UART(如果使用)
// uart_init();
7.1.3 恢复电源配置
c
// 确保 DC/DC 转换器保持开启
NRF_POWER->DCDCEN = 1;
// 清除电源监测标志
NRF_POWER->EVENTS_POFWARN = 0;
7.2 完整的退出低功耗模式函数示例
c
void lowpower_out_extent(void)
{
// 1. 启动 HFCLK
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK->TASKS_HFCLKSTART = 1;
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
// 2. 重新初始化外设
// 重新初始化 SAADC
NRF_SAADC->ENABLE = SAADC_ENABLE_ENABLE_Enabled;
// 重新初始化 NTC 电源
app_adc_set_ntc_pwr_en(true);
// 重新初始化 I2C
drv_i2c_init();
// 重新初始化 ADC
drv_adc_init();
// 3. 恢复 GPIO 配置
// 重新配置必要的 GPIO 引脚
// 例如:配置 UART 引脚
// nrf_gpio_cfg_output(_UART_TX_PIN);
// nrf_gpio_cfg_input(_UART_RX_PIN, NRF_GPIO_PIN_PULLUP);
}
7.3 时钟配置的注意事项
7.3.1 时钟启动顺序
- 先启动 HFCLK
- 然后重新初始化外设
- 最后恢复 GPIO 配置
7.3.2 外设初始化顺序
- 按照依赖关系初始化:
- 基础外设(I2C、SPI 等)
- 传感器(通过 I2C/SPI 连接的设备)
- 应用层外设(UART、ADC 等)
7.3.3 错误处理
- 添加时钟启动超时检测,防止系统卡死
- 检查外设初始化状态,确保正确恢复
7.4 优化建议
7.4.1 快速恢复
- 对于需要快速响应的应用,考虑使用内部 RC 振荡器启动 HFCLK
- 预留足够的启动时间,特别是外部晶振
7.4.2 功耗平衡
- 仅在需要时启动 HFCLK
- 完成任务后及时返回低功耗模式
7.4.3 状态保存
- 在进入低功耗模式前保存必要的状态
- 退出低功耗模式后恢复这些状态
7.5 实际应用示例
c
// 从低功耗模式唤醒后执行
void wakeup_from_lowpower(void)
{
// 1. 退出低功耗模式
lowpower_out_extent();
// 2. 执行必要的任务
// 例如:读取传感器数据
read_sensor_data();
// 3. 处理数据
process_data();
// 4. 重新进入低功耗模式
lowpower_in_extent();
}
通过正确配置退出低功耗模式时的时钟系统,可以确保设备快速恢复正常运行状态,同时保持良好的功耗表现。