• RTC相关实验


    RTC也就是实时时钟,用于记录当前系统时间,对于Linux系统而言时间是非常重要的,就和我们使用Windows电脑或手机查看时间一样,我们在使用Linux设备的时候也需要查看时间。

    Linux内核RTC驱动简介

    RTC设备驱动是一个标准的字符设备驱动,应用程序通过open、release、read、write和ioctl等函数完成对RTC设备的操作。

    原理详讲

    1、6U 内部自带到了一个 RTC 外设,确切的说是 SRTC。 6U 和 6ULL 的 RTC 内容在 SNVS
    章节。6U 的 RTC 分为 LP 和 HP。LP 叫做 SRTC,HP 是 RTC,但是 HP 的 RTC 掉电以后数据
    就丟失了,即使用了纽扣电池也没用。所以必须要使用 LP,也就是 SRTC。
    SNVS 章节有些是跟加密有关的,需要与 NXP 签订 NDA 协议才可以拿到。
    RTC 分为 SNVS_LP 和 SNVS_HP,4
    如果做产品,建议使用外置 RTC 芯片,PCF8563。
    RTC 很类似定时器,外接 32.768KHz 的晶振,然后就开始计时,RTC 使用两个寄存器来
    保存计数值。
    RTC 使用很简单,打开 RTC,然后 RTC 就开始工作,我们要做的就是不断地读取 RTC
    计数寄存器,获取时间值,或者向 RTC 计数器写入时间值,也就是调整时间。
    SNVS HPCOMR 的 bit31 置 1,表示所有的软件都可以访问 SNVS 所有寄存器。Bit8 也
    是和安全有关的,我们置 1,也可以不置 1.4
    SNVS_ LPCR 寄存器, bit0 置 1,开始 SRTC 功能。
    SNVS_LPSRTCMR 是高 32 为 RTC 计数寄存器
    SNVS_LPSRTCLR 是低 32 为 RTC 计数器,与 LPSRTCMR 共同组成了 SRTC 计数器,,每
    1 秒数据加 1。
    6U 的 RTC模式从 1970年1月1日0时0点0分0秒。

    主要代码:

     

    1. #include "bsp_rtc.h"
    2. #include "stdio.h"
    3. void rtc_init(void)
    4. {
    5. SNVS->HPCOMR |= (1 << 31) | (1 << 8);
    6. #if 0
    7. struct rtc_datetime rtcdate;
    8. rtcdate.year = 2018U;
    9. rtcdate.month = 12U;
    10. rtcdate.day = 13U;
    11. rtcdate.hour = 14U;
    12. rtcdate.minute = 52;
    13. rtcdate.second = 0;
    14. rtc_setDatetime(&rtcdate); //初始化时间和日期
    15. #endif
    16. rtc_enable(); //使能RTC
    17. }
    18. void rtc_enable(void)
    19. {
    20. /*
    21. * LPCR寄存器bit0置1,使能RTC
    22. */
    23. SNVS->LPCR |= 1 << 0;
    24. while(!(SNVS->LPCR & 0X01));//等待使能完成
    25. }
    26. void rtc_disable(void)
    27. {
    28. SNVS->LPCR &= ~(1 << 0);
    29. while(SNVS->LPCR & 0X01);//等待关闭完成
    30. }
    31. unsigned char rtc_isleapyear(unsigned short year)
    32. {
    33. unsigned char value=0;
    34. if(year % 400 == 0)
    35. value = 1;
    36. else
    37. {
    38. if((year % 4 == 0) && (year % 100 != 0))
    39. value = 1;
    40. else
    41. value = 0;
    42. }
    43. return value;
    44. }
    45. unsigned int rtc_coverdate_to_seconds(struct rtc_datetime *datetime)
    46. {
    47. unsigned short i = 0;
    48. unsigned int seconds = 0;
    49. unsigned int days = 0;
    50. unsigned short monthdays[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};
    51. for(i = 1970; i < datetime->year; i++)
    52. {
    53. days += DAYS_IN_A_YEAR; /* 平年,每年365天 */
    54. if(rtc_isleapyear(i)) days += 1;/* 闰年多加一天 */
    55. }
    56. days += monthdays[datetime->month];
    57. if(rtc_isleapyear(i) && (datetime->month >= 3)) days += 1;/* 闰年,并且当前月份大于等于3月的话加一天 */
    58. days += datetime->day - 1;
    59. seconds = days * SECONDS_IN_A_DAY +
    60. datetime->hour * SECONDS_IN_A_HOUR +
    61. datetime->minute * SECONDS_IN_A_MINUTE +
    62. datetime->second;
    63. return seconds;
    64. }
    65. void rtc_setdatetime(struct rtc_datetime *datetime)
    66. {
    67. unsigned int seconds = 0;
    68. unsigned int tmp = SNVS->LPCR;
    69. rtc_disable(); /* 设置寄存器HPRTCMR和HPRTCLR的时候一定要先关闭RTC */
    70. /* 先将时间转换为秒 */
    71. seconds = rtc_coverdate_to_seconds(datetime);
    72. SNVS->LPSRTCMR = (unsigned int)(seconds >> 17); /* 设置高16位 */
    73. SNVS->LPSRTCLR = (unsigned int)(seconds << 15); /* 设置地16位 */
    74. /* 如果此前RTC是打开的在设置完RTC时间以后需要重新打开RTC */
    75. if (tmp & 0x1)
    76. rtc_enable();
    77. }
    78. void rtc_convertseconds_to_datetime(u64 seconds, struct rtc_datetime *datetime)
    79. {
    80. u64 x;
    81. u64 secondsRemaining, days;
    82. unsigned short daysInYear;
    83. /* 每个月的天数 */
    84. unsigned char daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
    85. secondsRemaining = seconds; /* 剩余秒数初始化 */
    86. days = secondsRemaining / SECONDS_IN_A_DAY + 1; /* 根据秒数计算天数,加1是当前天数 */
    87. secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY; /*计算天数以后剩余的秒数 */
    88. /* 计算时、分、秒 */
    89. datetime->hour = secondsRemaining / SECONDS_IN_A_HOUR;
    90. secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR;
    91. datetime->minute = secondsRemaining / 60;
    92. datetime->second = secondsRemaining % SECONDS_IN_A_MINUTE;
    93. /* 计算年 */
    94. daysInYear = DAYS_IN_A_YEAR;
    95. datetime->year = YEAR_RANGE_START;
    96. while(days > daysInYear)
    97. {
    98. /* 根据天数计算年 */
    99. days -= daysInYear;
    100. datetime->year++;
    101. /* 处理闰年 */
    102. if (!rtc_isleapyear(datetime->year))
    103. daysInYear = DAYS_IN_A_YEAR;
    104. else /*闰年,天数加一 */
    105. daysInYear = DAYS_IN_A_YEAR + 1;
    106. }
    107. /*根据剩余的天数计算月份 */
    108. if(rtc_isleapyear(datetime->year)) /* 如果是闰年的话2月加一天 */
    109. daysPerMonth[2] = 29;
    110. for(x = 1; x <= 12; x++)
    111. {
    112. if (days <= daysPerMonth[x])
    113. {
    114. datetime->month = x;
    115. break;
    116. }
    117. else
    118. {
    119. days -= daysPerMonth[x];
    120. }
    121. }
    122. datetime->day = days;
    123. }
    124. unsigned int rtc_getseconds(void)
    125. {
    126. unsigned int seconds = 0;
    127. seconds = (SNVS->LPSRTCMR << 17) | (SNVS->LPSRTCLR >> 15);
    128. return seconds;
    129. }
    130. void rtc_getdatetime(struct rtc_datetime *datetime)
    131. {
    132. //unsigned int seconds = 0;
    133. u64 seconds;
    134. seconds = rtc_getseconds();
    135. rtc_convertseconds_to_datetime(seconds, datetime);
    136. }

     

     

  • 相关阅读:
    经过腾讯云这波故障,我想表扬的点和学到的职场保命法则。
    Mac软件打开时提示:已损坏,无法打开。你应该将它移到废纸娄。怎么解决?
    BCYD-A10-33-L85、BCYD-A16-21-S150电比例先导阀放大器
    计算机软件学习大方向
    高月薪&高年终如何抉择?
    `算法题解` `AcWing` 4617. 解方程
    建立基于Open vSwitch的GRE隧道
    WebStorm 运行 nodejs 脚本 路径不对
    Codeforces Round #813 (Div. 2)
    设备软件控制平台会是什么样子?
  • 原文地址:https://blog.csdn.net/qq_66545503/article/details/126336314