返回首页

RTC (实时时钟) 学习笔记

本笔记学习 Zephyr 的 RTC 驱动,用于实时时钟功能。


示例路径

zephyr/samples/drivers/rtc/

核心概念

RTC vs Timer

特性RTCTimer
功耗低功耗较高功耗
计时日历时间计数值
用途实时时钟、闹钟定时中断、延时
精度秒级微秒级

nRF54L15 是否可以直接使用该驱动、具体绑定到哪个 RTC 实例,以及哪些功能可用,要以当前板卡支持和设备树配置为准。


核心 API

头文件

#include <zephyr/drivers/rtc.h>

设备获取

const struct device *const rtc = DEVICE_DT_GET(DT_ALIAS(rtc));

设备就绪检查

if (!device_is_ready(rtc)) {
    printk("Device is not ready\n");
    return;
}

时间结构体

struct rtc_time {
    int tm_sec;   // 秒 [0-59]
    int tm_min;   // 分 [0-59]
    int tm_hour;  // 时 [0-23]
    int tm_mday;  // 日 [1-31]
    int tm_mon;   // 月 [0-11]
    int tm_year;  // 年 - 1900
    int tm_wday;  // 星期 [0-6]
    int tm_yday;  // 一年中的天数 [0-365]
    int tm_isdst; // 夏令时标志
};

设置时间

int rtc_set_time(const struct device *dev, const struct rtc_time *tm);

示例

struct rtc_time tm = {
    .tm_year = 2024 - 1900,  // 年份需要减 1900
    .tm_mon = 11 - 1,        // 月份需要减 1
    .tm_mday = 17,           // 日
    .tm_hour = 4,            // 时
    .tm_min = 19,            // 分
    .tm_sec = 0,             // 秒
};

int ret = rtc_set_time(rtc, &tm);
if (ret < 0) {
    printk("Cannot write date time: %d\n", ret);
}

读取时间

int rtc_get_time(const struct device *dev, struct rtc_time *tm);

示例

struct rtc_time tm;

int ret = rtc_get_time(rtc, &tm);
if (ret < 0) {
    printk("Cannot read date time: %d\n", ret);
    return ret;
}

printk("RTC date and time: %04d-%02d-%02d %02d:%02d:%02d\n",
       tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
       tm.tm_hour, tm.tm_min, tm.tm_sec);

完整示例代码

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/rtc.h>

const struct device *const rtc = DEVICE_DT_GET(DT_ALIAS(rtc));

static int set_date_time(const struct device *rtc)
{
    struct rtc_time tm = {
        .tm_year = 2024 - 1900,
        .tm_mon = 11 - 1,
        .tm_mday = 17,
        .tm_hour = 4,
        .tm_min = 19,
        .tm_sec = 0,
    };

    return rtc_set_time(rtc, &tm);
}

static int get_date_time(const struct device *rtc)
{
    struct rtc_time tm;
    int ret = rtc_get_time(rtc, &tm);
    
    if (ret < 0) {
        printk("Cannot read date time: %d\n", ret);
        return ret;
    }

    printk("RTC: %04d-%02d-%02d %02d:%02d:%02d\n",
           tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
           tm.tm_hour, tm.tm_min, tm.tm_sec);

    return ret;
}

int main(void)
{
    if (!device_is_ready(rtc)) {
        printk("RTC device is not ready\n");
        return 0;
    }

    set_date_time(rtc);

    while (get_date_time(rtc) == 0) {
        k_sleep(K_MSEC(1000));
    }
    
    return 0;
}

设备树配置示例

/ {
    aliases {
        rtc = &rtc0;
    };
};

&rtc0 {
    status = "okay";
};

编译命令

cd /home/wangpei/ncs-sdk
west build -p -b nrf54l15dk/nrf54l15/cpuapp zephyr/samples/drivers/rtc
west flash

运行结果示例

Cannot read date time: -ENOSYS

⚠️ 不同 SoC 和板卡对 RTC 驱动的支持程度不同,运行结果要以当前平台实际支持情况为准。

或者(如果配置正确):

RTC: 2024-11-17 04:19:00
RTC: 2024-11-17 04:19:01
RTC: 2024-11-17 04:19:02
...

应用场景

  1. 实时时钟: 维持系统日期时间
  2. 低功耗计时: 使用 RTC 代替高功耗定时器
  3. 日历功能: 日历应用、闹钟应用
  4. 事件时间戳: 记录事件发生时间

注意事项

  1. 时间格式: tm_year 需要减 1900,tm_mon 需要减 1
  2. 电池备份: RTC 需要电池备份才能在断电时保持时间
  3. 精度: RTC 通常精度较低(秒级)
  4. 初始化: 上电后需要设置初始时间

*小白 🤖 - 2026-03-16*