《RTC — RTC相关操作以及如何同步系统时间》

1.查看系统时间

date

 

 

2.查看RTC时间

  由于不同的RTC驱动读取时间的方法不一样。我这边使用的是hi_rtc。是使用海思中自动的测试程序。

./tim  -g  time

 

3.系统时间同步成RTC时间

hwclock –r         显示硬件时钟与日期

hwclock –s         将系统时钟调整为与目前的硬件时钟一致。

hwclock –w        将硬件时钟调整为与目前的系统时钟一致。

  但是我使用相关命令会出现:

 

   提示找不到相对应的设备节点。

  因为我的设备节点是加载在/dev/hi_rtc中,所以通用的这个是不行了。(海思的RTC不能使用通过的系统时间同步命令)

 

  利用mktime和settimeofday的直接在读取RTC时间时,将RTC时间再通过这两个函数再写入到系统时间中。

 

mktime函数:

  C 库函数 time_t mktime(struct tm *timeptr) 把 timeptr 所指向的结构转换为一个依据本地时区的 time_t 值。

#include <time.h>

time_t mktime(struct tm *timeptr)

参数:
struct tm {
   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;       /* 夏令时                        */    
};

返回值:
该函数返回一个 time_t 值,该值对应于以参数传递的日历时间。如果发生错误,则返回 -1 值。

  作用是,将时间转换为自1900年1月1日以来持续时间的秒数,发生错误时返回-1。(注意这边是自1900的1月份)

 

settimeofday函数:

#include<sys/time.h>
#include<unistd.h>

int settimeofday ( const struct timeval *tv,const struct timezone *tz);

参数:
struct  timeval{
       long  tv_sec;/**/
       long  tv_usec;/*微妙*/
};

struct  timezone{
        int tz_minuteswest;/*和greenwich 时间差了多少分钟*/
        int tz_dsttime;/*type of DST correction*/

}

返回值:函数执行成功后返回0,失败后返回-1,错误代码存于errno中。

 

4.实例

 

/*
 * RTC sample&test code.
 */

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>

#include "hi_rtc.h"

void usage(void)
{
    printf(
            "\n"
            "Usage: ./test [options] [parameter1] ...\n"
            "Options: \n"
            "    -s(set)            Set time/alarm,     e.g '-s time 2012/7/15/13/37/59'\n"
            "    -g(get)            Get time/alarm,     e.g '-g alarm'\n"
            "    -w(write)        Write RTC register, e.g '-w <reg> <val>'\n"
            "    -r(ead)            Read RTC register,  e.g '-r <reg>'\n"
            "    -a(alarm)        Alarm ON/OFF',      e.g '-a ON'\n"
            "    -reset            RTC reset\n"
            "    -b(battery monitor) battery ON/OFF,     e.g '-b ON'\n"
            "    -f(requency)        frequency precise adjustment, e.g '-f <val>'\n"
            "\n");
    exit(1);
}


static int _atoul(const char *str, unsigned char *pvalue)
{
    unsigned int result=0;

    while (*str)
    {
        if (isdigit((int)*str))
        {
            if ((result<429496729) || ((result==429496729) && (*str<'6')))
            {
                result = result*10 + (*str)-48;
            }
            else
            {
                *pvalue = result;
                return -1;
            }
        }
        else
        {
            *pvalue=result;
            return -1;
        }
        str++;
    }
    *pvalue=result;
    return 0;
}


#define ASC2NUM(ch) (ch - '0')
#define HEXASC2NUM(ch) (ch - 'A' + 10)

static int  _atoulx(const char *str, unsigned char *pvalue)
{
    unsigned int   result=0;
    unsigned char  ch;

    while (*str)
    {
        ch=toupper(*str);
        if (isdigit(ch) || ((ch >= 'A') && (ch <= 'F' )))
        {
            if (result < 0x10000000)
            {
                result = (result << 4) + ((ch<='9')?(ASC2NUM(ch)):(HEXASC2NUM(ch)));
            }
            else
            {
                *pvalue=result;
                return -1;
            }
        }
        else
        {
            *pvalue=result;
            return -1;
        }
        str++;
    }

    *pvalue=result;
    return 0;
}

/*used for convert hex value from string to int*/
static int str_to_num(const char *str, unsigned char *pvalue)
{
    if ( *str == '0' && (*(str+1) == 'x' || *(str+1) == 'X') ){
        if (*(str+2) == '\0'){
            return -1;
        }
        else{
            return _atoulx(str+2, pvalue);
        }
    }
    else {
        return _atoul(str,pvalue);
    }
}

/*used for convert time frome string to struct rtc_time_t*/
static int parse_string(char *string, rtc_time_t *p_tm)
{
    char *comma, *head;
    int value[10];
    int i;

    if (!string || !p_tm)
        return -1;

    if (!strchr(string, '/'))
        return -1;

    head = string;
    i = 0;
    comma = NULL;

    for(;;) {    
        comma = strchr(head, '/');

        if (!comma){
            value[i++] = atoi(head);
            break;
        }

        *comma = '\0';
        value[i++] = atoi(head);
        head = comma+1;    
    }
    
    if (i < 5)
        return -1;

    p_tm->year   = value[0];
    p_tm->month  = value[1];
    p_tm->date   = value[2];
    p_tm->hour   = value[3];
    p_tm->minute = value[4];
    p_tm->second = value[5];
    p_tm->weekday = 0;

    return 0;
}

int main(int argc, const char *argv[])
{
    struct tm tm_time;
    struct timeval val_time;
    rtc_time_t tm;
    reg_data_t regv;
    int ret = -1;
    int fd = -1;
    
    const char *dev_name = "/dev/hi_rtc";
    char string[50] = {0};

    if (argc < 2){
        usage();
        return 0;
    }

    fd = open(dev_name, O_RDWR);
    if (fd < 0) {
        printf("open %s failed\n", dev_name);
        return -1;
    }

    if (!strcmp(argv[1],"-s")) {
        if (argc < 4) {
            usage();
            goto err1;    
        }

        if (!strcmp(argv[2], "time")) {

            strncpy(string, argv[3], sizeof(string)-1);

            ret = parse_string(string, &tm);
            if (ret < 0)
            {
                printf("parse time param failed\n");
                goto err1;
            }
            printf("set time\n");

            /* code */
            printf("year:%d\n", tm.year);
            printf("month:%d\n",tm.month);
            printf("date:%d\n", tm.date); 
            printf("hour:%d\n", tm.hour);
            printf("minute:%d\n", tm.minute);
            printf("second:%d\n", tm.second);

            ret = ioctl(fd, HI_RTC_SET_TIME, &tm);
            if (ret < 0) {
                printf("ioctl: HI_RTC_SET_TIME failed\n");
                goto err1;
            }    
        } 
        else if (!strcmp(argv[2], "alarm")) 
        {
            strncpy(string, argv[3], sizeof(string)-1);

            ret = parse_string(string, &tm);
            if (ret < 0) {
                printf("parse alarm param failed\n");
                goto err1;
            }
            printf("set alarm\n");
#if 1            
            printf("year:%d\n", tm.year);
            printf("month:%d\n",tm.month);
            printf("date:%d\n", tm.date); 
            printf("hour:%d\n", tm.hour);
            printf("minute:%d\n", tm.minute);
            printf("second:%d\n", tm.second);
#endif            
            ret = ioctl(fd, HI_RTC_ALM_SET, &tm);
            if (ret < 0) {
                printf("ioctl: HI_RTC_ALM_SET failed\n");
                goto err1;
            }    
         } else {
            printf("unknown options %s\n", argv[2]);
            goto err1;
        }
    } else if (!strcmp(argv[1],"-g")) {
        if (argc < 3) {
            usage();
            goto err1;    
        }

        //read RTC
        if (!strcmp(argv[2], "time")) {

            printf("[RTC_RD_TIME]\n");
            
            ret = ioctl(fd, HI_RTC_RD_TIME, &tm);
            if (ret < 0) {
                printf("ioctl: HI_RTC_RD_TIME failed\n");
                goto err1;
            }
            
            printf("Current time value: \n");
        } else if (!strcmp(argv[2], "alarm")) {
        
            printf("[RTC_RD_ALM]\n");

            ret = ioctl(fd, HI_RTC_ALM_READ, &tm);
            if (ret < 0) {
                printf("ioctl: HI_RTC_ALM_READ failed\n");
                goto err1;
            }
            
            printf("Current alarm value: \n");
        } else {
            printf("unknow options %s\n", argv[2]);
            goto err1;
        }

        printf("year %d\n", tm.year);
        printf("month %d\n", tm.month);
        printf("date %d\n", tm.date);
        printf("hour %d\n", tm.hour);
        printf("minute %d\n", tm.minute);
        printf("second %d\n", tm.second);
        printf("weekday %d\n", tm.weekday);

        tm_time.tm_year        = tm.year - 1900;
        tm_time.tm_mon        = tm.month -1;
        tm_time.tm_mday        = tm.date;
        tm_time.tm_hour        = tm.hour;
        tm_time.tm_min        = tm.minute;
        tm_time.tm_sec        = tm.second;
        tm_time.tm_wday        = tm.weekday;
        
        val_time.tv_sec   = mktime(&tm_time);
        val_time.tv_usec        = 0;
        settimeofday(&val_time,NULL);

        
    } else if (!strcmp(argv[1],"-w")) {

        if (argc < 4) {
            usage();
            goto err1;
        }

        ret = str_to_num(argv[2], &(regv.reg));
        if (ret != 0) {
            printf("reg 0x%08x invalid\n", regv.reg);
            goto err1;
        }

        ret = str_to_num(argv[3], &(regv.val));
        if (ret != 0) {
            printf("val 0x%08x invalid\n", regv.val);
            goto err1;
        }
        
        printf("\n");
        printf("[RTC_REG_SET] reg:%02x, val:%02x\n", regv.reg, regv.val);
        printf("\n");

        ret = ioctl(fd, HI_RTC_REG_SET, &regv);
        if (ret < 0) {
            printf("ioctl: HI_RTC_REG_SET failed\n");
            goto err1;
        }

    } else if (!strcmp(argv[1],"-r")) {

        if (argc < 3) {
            usage();
            goto err1;
        }
        
        ret = str_to_num(argv[2], &(regv.reg));
        if (ret != 0) {
            printf("reg 0x%08x invalid\n", regv.reg);
            goto err1;
        }

        regv.val = 0;

        ret = ioctl(fd, HI_RTC_REG_READ, &regv);
        if (ret < 0) {
            printf("ioctl: HI_RTC_REG_READ failed\n");
            goto err1;
        }

        printf("\n");
        printf("[RTC_REG_GET] reg:0x%02x, val:0x%02x\n", regv.reg, regv.val);
        printf("\n");
    } else if (!strcmp(argv[1],"-a")) {

        if (argc < 3) {
            usage();
            goto err1;
        }

        if (!strcmp(argv[2], "ON")) {
            ret = ioctl(fd, HI_RTC_AIE_ON);
        } else if (!strcmp(argv[2], "OFF")) {
            ret = ioctl(fd, HI_RTC_AIE_OFF);
        }

        if (ret < 0) {
            printf("ioctl: HI_RTC_AIE_ON/OFF failed\n");
            goto err1;
        }

    } else if (!strcmp(argv[1],"-reset")) {

        printf("[RTC_RESET]\n");

        ret = ioctl(fd, HI_RTC_RESET);
        if(ret){
            printf("reset err\n");
            goto err1;
        }
    } else if (!strcmp(argv[1], "-b")) {

        if (argc < 3) {
            usage();
            goto err1;
        }

        if (!strcmp(argv[2], "ON")) {
            //printf("RTC temperature compensation on!\n");
            ret = ioctl(fd, HI_RTC_BM_ON);
        } else if (!strcmp(argv[2], "OFF")) {
            //printf("RTC temperature compensation off!\n");
            ret = ioctl(fd, HI_RTC_BM_OFF);
        }

        if (ret < 0) {
            printf("ioctl: HI_RTC_BM_ON/OFF failed\n");
            goto err1;
        }
    } else if (!strcmp(argv[1], "-f")) {
        
        unsigned int freq;
        rtc_freq_t value;
        
        // print current frequency value
        if (argc  < 3)
        {
            ret = ioctl(fd, HI_RTC_GET_FREQ, &value);
            if (ret < 0)
            {
                printf("get current frequency failed\n");
                goto err1;
            }    
            
            freq = value.freq_l;
            printf("current frequency : %d\n", freq);    
        }    
        // set frequency 
        else if (argc == 3)
        {
            freq = atoi(argv[2]);
            
            if (freq > 3277600 || freq < 3276000)
            {
                printf("invalid freq %d\n", freq);
                goto err1;
            }
        
            value.freq_l = freq;
            
            ret = ioctl(fd, HI_RTC_SET_FREQ, &value);
            if (ret < 0)
            {
                printf("get current frequency failed\n");
                goto err1;
            }
        }

    } else {
        printf("unknown download mode.\n");
        goto err1;
    }

err1:
    close(fd);

    return 0;
}

 

  以上是基于海思SDK中的/drv/rtc中的rtc_test.c修改的,修改的部分如下。(上面代码已经是修改完的了,下面的代码是从上面代码中截取出来的)

 

    struct tm tm_time;
    struct timeval val_time;

//读取RTC时间,放在结构体变量tm中
        ret = ioctl(fd, HI_RTC_RD_TIME, &tm);

    printf("year %d\n", tm.year);
    printf("month %d\n", tm.month);
    printf("date %d\n", tm.date);
    printf("hour %d\n", tm.hour);
    printf("minute %d\n", tm.minute);
    printf("second %d\n", tm.second);
    printf("weekday %d\n", tm.weekday);

        tm_time.tm_year        = tm.year - 1900;
        tm_time.tm_mon        = tm.month -1;
        tm_time.tm_mday        = tm.date;
        tm_time.tm_hour        = tm.hour;
        tm_time.tm_min        = tm.minute;
        tm_time.tm_sec        = tm.second;
        tm_time.tm_wday        = tm.weekday;
        
        val_time.tv_sec   = mktime(&tm_time);
        val_time.tv_usec        = 0;
        settimeofday(&val_time,NULL);
posted @ 2019-12-17 11:16  一个不知道干嘛的小萌新  阅读(2775)  评论(0编辑  收藏  举报