目录
2. Arduino添加 “RTC每秒打印时间信息” Sketch code
关于PKE8720DF-C13-F10开发板 的具体介绍请参考:Arduino 配置PKE8720DF-C13-F10开发板——“Blink” 周期性点亮LED灯_zoey_O_o__的博客-CSDN博客
1. RTC 简介
RTC(Real Time Clock)是一个独立的二进码十进制格式(BCD码)定时器/计数器。其中一个32位寄存器包括BCD格式表示的seconds、minutes、hours(12或24小时制),另一个32位寄存器包括二进制格式表示的days。BCD码是用4位二进制数来表示1位十进制数中的0~9这10个数码。另外可以自动将月份的天数计为28、29(闰年)、30、31天以及夏令时补偿。
只要工作电压维持在运行范围,不管在运行模式、低功耗模式还是重置情况下,RTC都不会停止。
2. Arduino添加 “RTC每秒打印时间信息” Sketch code
由于Arduino 基于board“ AMB25/AMB26 (RTL8720DF) ”没有直接可用的RTC Examples,这里我们需要自己新建一个sketch:
具体code 如下:
#include "rtc_api.h"
#include "wait_api.h"
void setup() {
// put your setup code here, to run once:
rtc_init();
rtc_write(1256729737); // Set RTC time to Wed, 28 Oct 2009 11:35:37
}
void loop() {
// put your main code here, to run repeatedly:
time_t seconds;
struct tm *timeinfo;
while(1) {
seconds = rtc_read();
timeinfo = localtime(&seconds);
DiagPrintf("Time as seconds since January 1, 1970 = %d\n", seconds);
DiagPrintf("Time as a basic string = %s", ctime(&seconds));
DiagPrintf("Time as a custom formatted string = %d-%d-%d %d:%d:%d\n",
timeinfo->tm_year+1900, timeinfo->tm_mon+1, timeinfo->tm_mday, timeinfo->tm_hour,
timeinfo->tm_min,timeinfo->tm_sec);
wait(1.0);
}
}
3.代码解析
包含的2个头文件 "rtc_api.h"和 "wait_api.h" 为了调用实现RTC 功能的函数,可以在源码中查询GitHub - ambiot/ambd_arduino: AmebaD Arduino third-party package SDK
(1)setup函数:
rtc_init:初始化RTC 设备,包括时钟,RTC寄存器和功能函数,具体代码如下:
void rtc_init(void)
{
RTC_InitTypeDef RTC_InitStruct;
RCC_PeriphClockSource_RTC(0);
RTC_StructInit(&RTC_InitStruct);
RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;
RTC_Init(&RTC_InitStruct);
RTC_BypassShadowCmd(ENABLE);
/* 32760 need add need add 15 cycles (256Hz) every 4 min*/
//RTC_SmoothCalibConfig(RTC_CalibSign_Positive, 15,
// RTC_CalibPeriod_4MIN, RTC_Calib_Enable);
rtc_en = 1;
}
rtc_write(seconds):从1970.1.1 00:00:00到要设置的指定数据和时间的秒数,具体代码如下:
void rtc_write(time_t t)
{
/* Convert the time in to a tm*/
struct tm *timeinfo = localtime(&t);
RTC_TimeTypeDef RTC_TimeStruct;
/*set time in RTC */
RTC_TimeStruct.RTC_H12_PMAM = RTC_H12_AM;
RTC_TimeStruct.RTC_Days = timeinfo->tm_yday;
RTC_TimeStruct.RTC_Hours = timeinfo->tm_hour;
RTC_TimeStruct.RTC_Minutes = timeinfo->tm_min;
RTC_TimeStruct.RTC_Seconds = timeinfo->tm_sec;
RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
/* Set rtc_timeinfo*/
_memcpy((void*)&rtc_timeinfo, (void*)timeinfo, sizeof(struct tm));
}
rtc_write(1256729737); // Set RTC time to Wed, 28 Oct 2009 11:35:37
1256729737就是从1970.1.1 00:00:00 到 2009.10.28 11:35:37 经过的秒数,如果要切换到其他时间点,则直接在rtc_write(/*填所需要的秒数*/)。
(2)loop 函数:
先定义两个时间变量: time_t seconds; struct tm *timeinfo;
赋值:seconds = rtc_read(); 从RTC获取以秒为单位的当前时间戳。RTC当前时间戳是以1970.1.1 00:00:00.开始计算的。
具体为什么是这个时间点:看到有这样解释:很多编程语言起源于UNIX系统,而UNIX系统认为1970年1月1日0点是时间起点,所以我们常说的UNIX时间戳是以1970年1月1日0点为计时起点时间的;还有的是:最早出现的UNIX操作系统考虑到计算机产生的年代和应用的时限综合取了1970年1月1日作为UNIX TIME的开始时间。
rtc_read函数代码具体如下:
time_t rtc_read(void)
{
time_t t;
struct tm tm_temp;
RTC_TimeTypeDef RTC_TimeStruct;
u32 delta_days = 0;
RRAM_TypeDef* RRAM = ((RRAM_TypeDef *) RRAM_BASE);
if((0x80000000&(RRAM->RTC_YEAR)) !=0){
rtc_restore_timeinfo();
RRAM->RTC_YEAR&=(~0x80000000);
}
_memcpy((void*)&tm_temp, (void*)&rtc_timeinfo, sizeof(struct tm));
/*hour, min, sec get from RTC*/
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct);
tm_temp.tm_sec = RTC_TimeStruct.RTC_Seconds;
tm_temp.tm_min = RTC_TimeStruct.RTC_Minutes;
tm_temp.tm_hour = RTC_TimeStruct.RTC_Hours;
/* calculate how many days later from last time update rtc_timeinfo */
delta_days = RTC_TimeStruct.RTC_Days - tm_temp.tm_yday;
/* calculate wday, mday, yday, mon, year*/
tm_temp.tm_wday += delta_days;
if(tm_temp.tm_wday >= 7){
tm_temp.tm_wday = tm_temp.tm_wday % 7;
}
tm_temp.tm_yday += delta_days;
tm_temp.tm_mday += delta_days;
while(tm_temp.tm_mday > days_in_month(tm_temp.tm_mon, tm_temp.tm_year)){
tm_temp.tm_mday -= days_in_month(tm_temp.tm_mon, tm_temp.tm_year);
tm_temp.tm_mon++;
if(tm_temp.tm_mon >= 12){
tm_temp.tm_mon -= 12;
tm_temp.tm_yday -= is_leap_year(tm_temp.tm_year) ? 366 : 365;
tm_temp.tm_year ++;
/* over one year, update days in RTC_TR */
RTC_TimeStruct.RTC_Days = tm_temp.tm_yday;
RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
/* update rtc_timeinfo */
_memcpy((void*)&rtc_timeinfo, (void*)&tm_temp, sizeof(struct tm));
}
}
/* Convert to timestamp(seconds from 1970.1.1 00:00:00)*/
t = mktime(&tm_temp);
return t;
}
赋值:timeinfo = localtime(&seconds); 将seconds 从unsigned long 转换为 struct tm (年月日时分秒)的格式。
DiagPrintf("Time as seconds since January 1, 1970 = %d\n", seconds);
第一条打印seconds的值,这里即1256729737;
DiagPrintf("Time as a basic string = %s", ctime(&seconds));
第二条打印ctime 格式的字符串;
DiagPrintf("Time as a custom formatted string = %d-%d-%d %d:%d:%d\n",
timeinfo->tm_year+1900, timeinfo->tm_mon+1, timeinfo->tm_mday, timeinfo->tm_hour,
timeinfo->tm_min,timeinfo->tm_sec);
第三条打印习惯格式(年月日用“-”分割,时分秒用“:”分割)。
之后每秒打印一次。
4.电路连接
(1)材料准备
- 1 块 PKE8720DF-C13-F10开发板
- 1 根 USB转type-C数据线
(2)电路连接
将typc-c连接开发板,USB连接电脑。
(3)端口设置与烧录
请参考上一篇文章:Arduino 配置PKE8720DF-C13-F10开发板 —— UART回送用户输入的单个字符_zoey_O_o__的博客-CSDN博客
5.实验结果
打开串口调试工具,进行如下setting:
按板子上的RESET按键,这时候可以看到tool开始打印时间相关的信息,三条打印信息为一组,每秒打印一组,如果给板子一直供电,时间相关的信息会一直打印。
实验结果符合预期。