Skip to content

RTC设备

RTC简介

RTC(Real-Time Clock)实时时钟可以提供精确的实时时间,它可以用于产生年、月、日、时、分、秒等信息。UC8288采用内部32.768KHz时钟作为RTC时钟源。并且添加RTC报警功能,设置RTC报警日期和时间后在RTC设备计时到达后会产生一个RTC报警中断。

驱动支持

访问RTC设备前,需要保证相关驱动配置已选中。

Windows环境:利用RT-Thread官方env工具直接在代码根目录下执行menuconfig进入配置。

Linux环境:在代码根目录下执行scons --menuconfig进入配置。

RTC驱动所在路径如下:

RT-Thread Components -> Device Drivers -> Using RTC device drivers

访问 RTC 设备

在开启 RTC 设备框架以及 RTC 驱动之后,用户可以 #include <sys/time.h> 用来引用标准的时间操作函数(例如 time、ctime、stime、mktime等,具体使用方法可以百度)。在Unix系统或者Windows系统下怎么使用 <time.h> 里边的函数,在RT-Thread下就怎么使用。建议用户采用标准库时间函数来操作 RTC。

此外,RTC 设备框架也提供了 set_date()set_time() 函数,方便用户快速修改时间和日期,但是该函数在例如一些特殊时刻设置时间、日期(例如2023年12月31日23时59分59秒)时可能会导致错误,因此一般用于测试 RTC 硬件是否工作正常和一些简单的演示时使用,不建议在业务代码中使用。

函数 描述
set_date() 设置日期,年、月、日(当地时区)
set_time() 设置时间,时、分、秒(当地时区)

设置日期

通过如下函数设置 RTC 设备当前当地时区日期值:

rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day)
参数 描述
year 待设置生效的年份
month 待设置生效的月份
day 待设置生效的日
返回 ——
RT_EOK 设置成功
-RT_ERROR 失败,没有找到 rtc 设备
其他错误码 失败

使用示例如下所示:

/* 设置日期为2018年12月3号 */
set_date(2018, 12, 3);

设置时间

通过如下函数设置 RTC 设备当前当地时区时间值:

rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second)
参数 描述
hour 待设置生效的时
minute 待设置生效的分
second 待设置生效的秒
返回 ——
RT_EOK 设置成功
-RT_ERROR 失败,没有找到 rtc 设备
其他错误码 失败

使用示例如下所示:

/* 设置时间为11点15分50秒 */
set_time(11, 15, 50);

获取当前时间

使用到 C 标准库中的时间 API 获取时间戳(格林威治时间):

time_t time(time_t *t)
参数 描述
t 时间数据指针
返回 ——
当前时间值

使用示例如下所示:

time_t now;     /* 保存获取的当前时间值 */
/* 获取时间 */
now = time(RT_NULL);
/* 打印输出时间信息 */
rt_kprintf("%s\n", ctime(&now));

Note

注:目前系统内只允许存在一个 RTC 设备,且名称为 "rtc"

RTC使用示例

使用示例需要配置menuconfig,使能例程与外设,步骤如下:

  1. 使能例程
Application Example Config -> Enable RTC Example
  1. 使能外设驱动
Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable RTC

以下提供RTC测试实例,测试步骤如下:

  1. 根据RTC设备名称,获取RTC设备句柄。
  2. 设置RTC输出。
#include <rtthread.h>
#ifdef APP_EXAMPLE_RTC

#ifndef RT_USING_RTC
#error "Please enable rt-thread rtc device driver"
#endif

#ifndef BSP_USING_RTC
#error "Please enable on-chip peripheral rtc config"
#endif

#include <rtdevice.h>
#include "uc_rtc_app.h"

#define THREAD_STACK_SIZE 512
#define THREAD_PRIORITY 5
#define THREAD_TIMESLICE 5

#define RTC_DEVICE_NAME "rtc"
static rt_device_t rtc_device = RT_NULL;

#ifdef RT_USING_ALARM

static void user_alarm_callback(rt_alarm_t alarm, time_t timestamp)
{
    rt_kprintf("user alarm callback function. alarm flag: 0x%x, timestamp: %d\n", alarm->flag, timestamp);
}

static void rtc_alarm_app_sample(void)
{
    struct rt_alarm_setup setup;
    struct rt_alarm *alarm = RT_NULL;
    static time_t now;
    struct tm p_tm;

    /* 获取当前时间戳,并把下5秒时间设置为闹钟时间 */
    /* 闹钟第一次响起在当前时间的1分5秒后,之后每隔1分钟响起 */
    now = time(NULL) + 5;
    gmtime_r(&now, &p_tm);

    setup.flag = RT_ALARM_MINUTE;
    setup.wktime.tm_year = p_tm.tm_year;
    setup.wktime.tm_mon = p_tm.tm_mon;
    setup.wktime.tm_mday = p_tm.tm_mday;
    setup.wktime.tm_wday = p_tm.tm_wday;
    setup.wktime.tm_hour = p_tm.tm_hour;
    setup.wktime.tm_min = p_tm.tm_min;
    setup.wktime.tm_sec = p_tm.tm_sec;

    alarm = rt_alarm_create(user_alarm_callback, &setup);
    if (alarm == RT_NULL)
    {
        rt_kprintf("create alarm failed.\n");
    }
    else
    {
        rt_alarm_start(alarm);
    }
}

#endif

static void rtc_thread_entry(void *parameter)
{
    time_t now;
    while (1)
    {
        /* 延时5秒 */
        rt_thread_mdelay(5000);
        /* 获取时间 */
        now = time(RT_NULL);
        rt_kprintf("%s", ctime(&now));
    }
}

int rtc_app_sample(void)
{
    rt_err_t ret = RT_EOK;
    rt_thread_t thread = RT_NULL;

    rt_kprintf("rtc_app_sample\n");

    /*寻找设备*/
    rtc_device = rt_device_find(RTC_DEVICE_NAME);
    if (!rtc_device)
    {
        rt_kprintf("find %s failed!\n", RTC_DEVICE_NAME);
        return -RT_ERROR;
    }

    /*初始化RTC设备*/
    if (rt_device_open(rtc_device, 0) != RT_EOK)
    {
        rt_kprintf("open %s failed!\n", RTC_DEVICE_NAME);
        return -RT_ERROR;
    }

    /* 设置日期 */
    ret = set_date(2020, 1, 1);
    if (ret != RT_EOK)
    {
        rt_kprintf("set RTC date failed\n");
        return ret;
    }

    /* 设置时间 */
    ret = set_time(0, 0, 0);
    if (ret != RT_EOK)
    {
        rt_kprintf("set RTC time failed\n");
        return ret;
    }

#ifdef RT_USING_ALARM
    rtc_alarm_app_sample();
#endif

    /* 创建线程 */
    thread = rt_thread_create("rtc_app",
                              rtc_thread_entry,
                              RT_NULL,
                              THREAD_STACK_SIZE,
                              THREAD_PRIORITY,
                              THREAD_TIMESLICE);
    /* 创建成功则启动线程 */
    if (RT_NULL == thread)
    {
        return -RT_ERROR;
    }
    else
    {
        rt_thread_startup(thread);
    }

    return RT_EOK;
}

#endif
Back to top