2023/06/28

[程式設計] Arduino新版編譯Compiled Time更新RTC Time造成日期錯誤的問題

隨著Arduino程式庫更新之後,下面的程式碼就會有錯誤,明明編譯的時間是28 Jun 2023,套入RtcDateTime(__DATE__, __TIME__)之後卻變成2023-07-04,整個日期就跑掉了,找了很多方法之後都無法修正這個問題,網路上也找不到更好的做法,於是我提供一個自己修正的版本。

#include <time.h>
#include <ThreeWire.h>
#include <RtcDS1302.h>

ThreeWire RtcWire(21, 22, 15);		// IO, SCLK, CE
RtcDS1302 RTC(RtcWire);	// RTC模組連線

void setup() {
	// 初始化RTC時鐘
	RtcWire.begin();
	vTaskDelay(10 / portTICK_PERIOD_MS);
	RTC.Begin();
	vTaskDelay(10 / portTICK_PERIOD_MS);
	
	// 取出編譯日期時間
	RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
	// 印出編譯完成的日期時間
	printDateTime("compiled", compiled);
	
	// RTC時鐘初始化失敗
	if (!RTC.IsDateTimeValid()) {
		Serial.println("[TIME] RTC lost confidence in the DateTime!");
		RTC.SetDateTime(compiled);
		vTaskDelay(10 / portTICK_PERIOD_MS);
	}
	if (RTC.GetIsWriteProtected()) {
		Serial.println("[TIME] RTC was write protected, enabling writing now");
		RTC.SetIsWriteProtected(false);
		vTaskDelay(10 / portTICK_PERIOD_MS);
	}
	if (!RTC.GetIsRunning()) {
		Serial.println("[TIME] RTC was not actively running, starting now");
		RTC.SetIsRunning(true);
		vTaskDelay(10 / portTICK_PERIOD_MS);
	}
	
	// 獲取RTC時間
	RtcDateTime rtctime = RTC.GetDateTime();
	// 印出RTC時鐘日期時間
	printDateTime("rtctime", rtctime);
	
	// 更新RTC時鐘
	if (rtctime < compiled) {
		// 如果讀出的時間早於系統時間,則重新設置RTC時間
		Serial.println("[TIME] RTC is older than compile time!	(Updating DateTime)");
		RTC.SetDateTime(compiled);
		vTaskDelay(10 / portTICK_PERIOD_MS);
		rtctime = RTC.GetDateTime();	// 得到RTC的時間
		printDateTime("rtc", rtctime);
	} else if (rtctime > compiled) {
		// 如果讀出的時間晚於系統時間,則重新設置RTC時間
		Serial.println("[TIME] RTC is newer than compile time.");
	} else if (rtctime == compiled) {
		Serial.println("[TIME] RTC is the same as compile time!");
	}
}
void loop() {

}
// 印出日期時間
void printDateTime(String subject, const RtcDateTime& dt) {
	char datestring[25];
	snprintf_P(
		datestring,
		countof(datestring),
		PSTR("%04u-%02u-%02u %02u:%02u:%02u"),
		dt.Year(),
		dt.Month(),
		dt.Day(),
		dt.Hour(),
		dt.Minute(),
		dt.Second()
	);
	Serial.println("[DATETIME] " + subject + " = " + String(datestring));
}

改成使用timeinfo格式去填入就能解決日期跑掉的問題了。

/* 舊方法
// 取出編譯日期時間
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
*/
// 新方法
// setp1. 上面新增新的include
#include <ctime>
// setp2. 程式碼改為
struct tm timeinfo;
// 使用 strptime 解析日期字符串
strptime(__DATE__, "%b %d %Y", &timeinfo);
// 使用 strptime 解析時間字符串
strptime(__TIME__, "%H:%M:%S", &timeinfo);
// 創建 RtcDateTime 物件
RtcDateTime compiled = RtcDateTime(
	timeinfo.tm_year - 100,   // 年份 = -100 (西元)
	timeinfo.tm_mon + 1,      // 月份 = +1 (0-11)
	timeinfo.tm_mday,
	timeinfo.tm_hour,
	timeinfo.tm_min,
	timeinfo.tm_sec
);
// 印出編譯完成的日期時間
printDateTime("compiled", compiled);

沒有留言:

張貼留言