如何用C语言编写统计运行天数的程序/函数(含Arduino场景)
统计程序运行天数的C语言实现(含Arduino项目适配)
一、通用C语言方案(桌面/服务器程序)
利用标准库<time.h>的时间戳功能,通过记录首次运行的时间戳,每次调用时计算与当前时间的差值,转换为天数。核心是用静态变量保存首次运行时间,确保函数内部状态持久化。
代码实现
#include <time.h> #include <stdio.h> int get_running_days() { static time_t start_time = 0; // 静态变量,仅初始化一次 time_t current_time; // 首次调用时记录初始时间 if (start_time == 0) { if (time(&start_time) == -1) { perror("Failed to get system time"); return -1; // 时间获取失败返回错误码 } return 0; // 首次执行返回0天 } // 获取当前时间并计算差值 if (time(¤t_time) == -1) { perror("Failed to get system time"); return -1; } // 计算秒数差,转换为天数(一天=86400秒) double elapsed_days = difftime(current_time, start_time) / 86400.0; return (int)elapsed_days; // 取整数部分,按完整24小时周期统计 } // 测试示例 int main() { printf("First call: %d days\n", get_running_days()); // 模拟延迟(实际运行中无需此代码) // sleep(86400 * 3); printf("After 3 days: %d days\n", get_running_days()); return 0; }
注意事项
- 依赖系统时钟的准确性,若系统时间被修改,统计结果会受影响。
difftime()处理时间戳差值,避免溢出问题(time_t通常为64位,无需担心长期运行溢出)。
二、Arduino项目专用方案
Arduino场景分两种情况:单次运行不保留断电状态、断电后需继续统计(依赖RTC模块)。
1. 无RTC模块(单次运行)
利用Arduino内置的millis()函数获取开机后的毫秒数,通过静态变量记录首次调用时间,计算天数差。需注意millis()的溢出(unsigned long类型约49天溢出,但unsigned减法会自动处理溢出)。
代码实现
unsigned long get_running_days() { static unsigned long start_millis = 0; unsigned long current_millis = millis(); // 首次调用初始化 if (start_millis == 0) { start_millis = current_millis; return 0; } // 计算毫秒差,转换为天数 unsigned long elapsed_ms = current_millis - start_millis; return elapsed_ms / (1000UL * 60 * 60 * 24); // UL确保无溢出 } // 使用示例(在loop中调用) void setup() { Serial.begin(9600); } void loop() { unsigned long days = get_running_days(); Serial.print("Running days: "); Serial.println(days); // 基于天数的条件判断示例 if (days >= 60 && days <= 90) { digitalWrite(LED_BUILTIN, HIGH); } else { digitalWrite(LED_BUILTIN, LOW); } delay(1000); }
2. 带RTC模块(断电持久化)
若设备需要断电后继续统计天数,需搭配RTC模块(如DS3231),通过Unix时间戳记录首次运行时间,重启后从RTC读取当前时间计算差值。
代码实现(以DS3231为例)
#include <Wire.h> #include <DS3231.h> DS3231 rtc; static time_t start_timestamp = 0; // 保存首次运行的Unix时间戳 unsigned int get_running_days() { // 首次调用或重启后初始化 if (start_timestamp == 0) { start_timestamp = rtc.getUnixTime(); return 0; } time_t current_timestamp = rtc.getUnixTime(); double elapsed_days = difftime(current_timestamp, start_timestamp) / 86400.0; return (unsigned int)elapsed_days; } void setup() { Serial.begin(9600); Wire.begin(); rtc.begin(); // 可选:若RTC未设置时间,可初始化(仅执行一次) // rtc.setDateTime(2024, 5, 20, 9, 50, 0); // 年,月,日,时,分,秒 } void loop() { unsigned int days = get_running_days(); Serial.print("Running days: "); Serial.println(days); // 60-90天的条件逻辑 if (days >= 60 && days <= 90) { // 执行设备控制逻辑 } delay(3600000); // 每小时刷新一次 }
关键说明
- 示例中按完整24小时周期统计天数(如周五9:50到周一9:50刚好3天),符合需求。
- 若需按自然日(跨零点就算一天),需额外解析RTC的年月日,实现日期差计算逻辑。
内容的提问来源于stack exchange,提问作者hollowaytyl
相关产品推荐
相关产品推荐

