Arduino IDE中C++毫秒转时间戳异常:时间戳递减问题排查
时间戳递减问题的修复方案
问题现象
串口输出的CSV格式数据中,时间戳出现递减情况,示例输出如下:
timestamp,lux 0:0:16,66 0:0:11,30 0:0:7,30 0:0:2,35 1:1:3,30 0:0:59,171 0:0:54,36 0:0:50,35 0:0:45,32
现有代码
用于生成CSV的函数:
void writeToCsv() { Serial.println("timestamp,lux"); unsigned timestamp = last_save; for (int i = 0; i < EEPROM.length(); i++) { int seconds = (int) (timestamp / 1000) % 60; int minutes = (int) ((timestamp / (1000*60)) % 60); int hours = (int) ((timestamp / (1000*60*60)) % 24); Serial.print(hours); Serial.print(":"); Serial.print(minutes); Serial.print(":"); Serial.print(seconds); Serial.print(","); Serial.println(EEPROM.read(i)); timestamp += LOGGING_DELAY; } last_save = timestamp; }
关键变量定义
#define LOGGING_DELAY 1 * 60 * 60 * 1000 #define HOUR 11 + (23/60) // 11:23 am (the starting time) int start_time = 1000 * 60 * 60 * HOUR
问题根源
- 变量类型溢出:多数嵌入式平台(如Arduino)的
int是16位类型,最大值仅为32767,而LOGGING_DELAY计算值为3600000,远超出int范围,导致数值溢出后变为负数。每次累加这个溢出的负数,会让timestamp实际递减,最终表现为时间戳倒退。 - 时间初始化错误:
23/60属于整数除法,结果为0,因此HOUR实际等于11,无法正确表示11:23的起始时间。
修复步骤
1. 修正变量类型
将所有存储毫秒数的变量改为unsigned long(32位无符号长整型,可容纳约49天的毫秒数,完全满足需求):
- 将
last_save的类型从int改为unsigned long - 将
start_time的类型从int改为unsigned long - 函数内的
timestamp改为unsigned long,避免局部变量溢出
2. 修正起始时间定义
替换原有的HOUR宏,直接计算起始时间的总毫秒数,避免整数除法丢失精度:
#define START_HOURS 11 #define START_MINUTES 23 unsigned long start_time = (unsigned long)(START_HOURS * 3600 + START_MINUTES * 60) * 1000;
3. 确保宏定义数值无溢出
给LOGGING_DELAY的数值加上UL后缀,强制编译器按无符号长整型处理,避免编译时溢出:
#define LOGGING_DELAY 1UL * 60UL * 60UL * 1000UL // 1小时对应的毫秒数
4. 调整writeToCsv函数
修改局部变量timestamp的类型:
void writeToCsv() { Serial.println("timestamp,lux"); unsigned long timestamp = last_save; // 改为unsigned long for (int i = 0; i < EEPROM.length(); i++) { int seconds = (int) (timestamp / 1000) % 60; int minutes = (int) ((timestamp / (1000*60)) % 60); int hours = (int) ((timestamp / (1000*60*60)) % 24); Serial.print(hours); Serial.print(":"); Serial.print(minutes); Serial.print(":"); Serial.print(seconds); Serial.print(","); Serial.println(EEPROM.read(i)); timestamp += LOGGING_DELAY; } last_save = timestamp; }
内容的提问来源于stack exchange,提问作者Nikita
相关产品推荐
相关产品推荐

