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测试实例,测试步骤如下:
- 根据RTC设备名称,获取RTC设备句柄。
- 设置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