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设备,库中提供了以下接口:

函数 描述
rt_device_find() 根据RTC名称查找设备获取设备句柄
rt_device_control() 控制RTC设备

查找RTC设备

查找RTC设备,函数原型如下所示:

rt_device_t rt_device_find(const char* name);

  • 参数

    [IN]name:RTC设备名称,目前注册到的系统中的RTC设备名称为"rtc"。

  • 返回值

    RT_NULL:失败,设备不存在。

    非RT_NULL:成功,该返回值是操作RTC设备的句柄,在后续的接口中作为函数入参。

控制RTC设备

控制RTC设备,函数原型如下所示:

rt_err_t rt_device_control(rt_device_t dev, int cmd, void* arg);

  • 参数

    [IN]dev:RTC设备句柄,查找RTC设备函数的返回值

    [IN]cmd:命令控制字,在这里主要支持以下宏定义:

    // 宏定义所在文件相对路径:
    // rt-thread/include/rtdef.h
    #define RT_DEVICE_CTRL_RTC_GET_TIME     0x10    // 获取时间
    #define RT_DEVICE_CTRL_RTC_SET_TIME     0x11    // 设置时间
    #define RT_DEVICE_CTRL_RTC_GET_ALARM    0x12    // 获取告警
    #define RT_DEVICE_CTRL_RTC_SET_ALARM    0x13    // 设置告警
    

    [INOUT]arg:

    • RT_DEVICE_CTRL_RTC_GET_TIME 与 RT_DEVICE_CTRL_RTC_SET_TIME 所需要的参数是 time_t 结构体指针, time_t 是 c 语言标准库中的一个结构
    • RT_DEVICE_CTRL_RTC_GET_ALARM 与 RT_DEVICE_CTRL_RTC_SET_ALARM 所需要的参数是 rtc_alarm_t 结构体指针, 定义在 uc_rtc.h 头文件中

    有关这几个参数的详细使用方法,请参考下面的使用示例

  • 返回值

    0,正常

    其他:错误,RT-Thread定义的错误类型。

RTC使用示例

使用示例需要配置menuconfig打开配置(默认关闭),路径如下:

wiota APP -> open rtc, default close(_RTC_APP_)

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

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

#define RTC_DEVICE_NAME    "rtc"

static rt_device_t rtc_dev = NULL;

void rtc_alarm_test(void);

int rtc_app_init(void)
{
    rt_err_t ret = RT_EOK;

    rtc_dev = rt_device_find(RTC_DEVICE_NAME);
    if (rtc_dev == RT_NULL)
    {
        rt_kprintf("find %s failed!\n", RTC_DEVICE_NAME);
        return RT_ERROR;
    }

    ret = rt_device_init(rtc_dev);
    if (ret != RT_EOK)
    {
        rt_kprintf("rtc device init failed!\n", RTC_DEVICE_NAME);
        return ret;
    }

    return ret;
}


void rtc_app_sample(void)
{
    int ret = 0;
    time_t rtc_time;
    struct tm set_time;

    rt_kprintf("rtc test demo.\r\n");

    ret = rtc_app_init();
    if(ret != RT_EOK)
    {
        rt_kprintf("init rtc error.\r\n");
        return;
    }

    /* make time 2000/1/1 00:00:00 */
    set_time.tm_sec      = 0;    /* Seconds: 0-60 (to accommodate leap seconds) */
    set_time.tm_min      = 0;    /* Minutes: 0-59 */
    set_time.tm_hour     = 0;    /* Hours since midnight: 0-23 */
    set_time.tm_mday     = 1;    /* Day of the month: 1-31 */
    set_time.tm_mon      = 0;    /* Months *since* January: 0-11 */
    set_time.tm_year     = 100;  /* Years since 1900 */
    set_time.tm_wday     = 6;    /* Days since Sunday (0-6), 0 is Sunday */
    set_time.tm_yday     = 0;    /* Days since Jan. 1: 0-365 */
    set_time.tm_isdst    = 0;    /* +1=Daylight Savings Time, 0=No DST, -1=unknown */

    rtc_time = mktime(&set_time);    /* Get the number of seconds after January 1, 1970 */

    rt_kprintf("rtc set time %d-%d-%d %02d:%02d:%02d\r\n", (set_time.tm_year + 1900), set_time.tm_mon + 1, set_time.tm_mday, set_time.tm_hour, set_time.tm_min, set_time.tm_sec);

    if(rtc_dev != NULL)
    {
        ret = rt_device_control(rtc_dev, RT_DEVICE_CTRL_RTC_SET_TIME, &rtc_time);
        if(ret != RT_EOK)
        {
            rt_kprintf("set rtc error, ret = %d\r\n", ret);
            return;
        }
        else
        {
            rt_kprintf("set rtc time ok\r\n");
        }

        /* alarm test */
        rtc_alarm_test();
    }
    else
    {
        rt_kprintf("rtc test error\r\n");
    }
}


void alarm_irq_handler(void *arg)
{
    int ret;
    time_t rtc_time;
    struct tm *now;

    ret = rt_device_control(rtc_dev, RT_DEVICE_CTRL_RTC_GET_TIME, &rtc_time);
    if(ret != RT_EOK)
    {
        rt_kprintf("get rtc value error, ret = %d\r\n", ret);
        return;
    }

    /* convert time_t to struct tm */
    now = localtime(&rtc_time);

    rt_kprintf("rtc alarm irq arrived, now time = %d-%d-%d %02d:%02d:%02d\r\n", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);

    /* disable rtc alarm irq */
    // rtc_disable_alarm_interrupt(UC_RTC);
    /* clear irq pending */
    rtc_clear_alarm_pending(UC_RTC);
}

void rtc_alarm_test(void)
{
    int ret = 0;
    rtc_alarm_t rtc_time = {0};

    rt_kprintf("alarm test demo\r\n");

    /* enable rtc irq */
    rtc_enable_alarm_interrupt(UC_RTC);

    /* set alarm 2000/1/1 00:00:05 */
    rtc_time.year = 2000;
    rtc_time.mon = 1;
    rtc_time.day = 1;
    rtc_time.hour = 0;
    rtc_time.min = 0;
    rtc_time.sec = 5;
    rtc_time.week = 6;
    rtc_time.mask = RTC_AM_YEAR | RTC_AM_MON | RTC_AM_DAY | RTC_AM_WEEK;

    /* set alarm irq */
    rtc_time.call_back = alarm_irq_handler;
    rtc_time.call_back_arg = NULL;

    ret = rt_device_control(rtc_dev, RT_DEVICE_CTRL_RTC_SET_ALARM, &rtc_time);
    if(ret != RT_EOK)
    {
        rt_kprintf("set alarm error, ret = %d\r\n", ret);
        return;
    }

    ret = rt_device_control(rtc_dev, RT_DEVICE_CTRL_RTC_GET_ALARM, &rtc_time);
    if(ret != RT_EOK)
    {
        rt_kprintf("get alarm error, ret = %d\r\n", ret);
    }
    else
    {
        rt_kprintf("set alarm time = %d-%d-%d %d:%d:%d, week = %d.\r\n", rtc_time.year, rtc_time.mon, rtc_time.day, rtc_time.hour, rtc_time.min, rtc_time.sec, rtc_time.week);
    }

}

#endif
Back to top