【小工具】系统时间SYSTEMTIME 轻量实现
来源:互联网 发布:91手机助手mac版 编辑:程序博客网 时间:2024/05/29 18:03
美丽的暑假被叫回来干活。要我改个3年前的嵌入式程序,马上项目要用。一看程序,亲娘滴,全部业务代码全部写在main.c文件中,大段大段的复制黏贴微改,任务间通信全用的轮询标志位╮(╯▽╰)╭。有强迫症的我用一周把整个程序重构了一遍,各模块分到不同的文件中,各种封装,同步的方式全改成异步。最后一算,扣掉操作系统的代码,代码量(CODE+DATA)减少了一半,这还是实现了许多原来没实现的功能后的,比原来更精简了操作系统的部分就不算它了。七天重构了个前人写了两个多月的程序,差点没把我累死。
因为之前做毕设的时候没时间好好封装系统时间模块,这次就顺带封装了一下,只实现了最基本的功能,一般的使用是够了。
由于嵌入式开发中没有提供系统时间,需要自己实现(不知道其他嵌入式操作系统有没有,反正uCOS是没有,它只是个内核),所以自己简单封装了个SYSTEMTIME模块。需要的自取。下面贴出代码:
/************************************************************************************************************* Systemtime SUPPORT PACKAGE* 系统时间支持包** File : SystemTime.h* By : Lin Shijun* Date : 2017/07/20* version: 1.0.0 * NOTE : 1. 此系统时间需要由外部驱动运作,典型地,在每增加1ms时关闭中断并调用Systemtime_Tick_Signal()* 来通知 系统时间模块 增加一毫秒* 2. 可以通过挂载事件来在年/月/日……增加时进行对应操作,但要注意这个事件是由调用Systemtime_Tick_Signal()的* 地方驱动的,如是在中断中调用的Systemtime_Tick_Signal(),则别执行中断中不能进行的操作。**********************************************************************************************************/#ifndef SYSTEM_TIME_H#define SYSTEM_TIME_H/*********************************************************************************************************** INCLUDES**********************************************************************************************************/#include <os_cpu.h>/*********************************************************************************************************** CONFIGURE**********************************************************************************************************/// 启动时初始化的时间设定#define SYSTEM_TIME_DEFAULT_YEAR 2017#define SYSTEM_TIME_DEFAULT_MONTH 7#define SYSTEM_TIME_DEFAULT_DAY 20#define SYSTEM_TIME_DEFAULT_HOUR 23#define SYSTEM_TIME_DEFAULT_MINUTE 59#define SYSTEM_TIME_DEFAULT_SECOND 50#define SYSTEM_TIME_DEFAULT_MSECOND 0// 是否使用对应事件#define SYSTEM_TIME_EVENT_ONMSECONDINC_EN FALSE#define SYSTEM_TIME_EVENT_ONSECONDINC_EN FALSE #define SYSTEM_TIME_EVENT_ONMINUTEINC_EN FALSE#define SYSTEM_TIME_EVENT_ONHOURINC_EN FALSE#define SYSTEM_TIME_EVENT_ONDAYINC_EN TRUE#define SYSTEM_TIME_EVENT_ONMONTHINC_EN FALSE#define SYSTEM_TIME_EVENT_ONYEARINC_EN FALSE/*********************************************************************************************************** DATATYPE 数据类型**********************************************************************************************************/typedef struct system_time{ INT16U wYear; // 年 INT16U wMonth; // 月 INT16U wDay; // 日 INT16U wHour; // 时 INT16U wMinute; // 分 INT16U wSecond; // 秒 INT16U wMSecond; // 毫秒} SYSTEM_TIME;typedef void (* SYSTEM_TIME_EVENT)(const SYSTEM_TIME *time);/*********************************************************************************************************** CONSTANT**********************************************************************************************************/// 定义空时间,便于比较赋值extern const SYSTEM_TIME* const TimeNull;/*********************************************************************************************************** FUNCTION PROTOTYPES 函数原型**********************************************************************************************************//********* 注意: 以下函数都不需考虑任务冲突之类的事情 **********/// 获取当前系统时间,用输入参数返回void SystemTime_get(SYSTEM_TIME *rst);// 设置当前系统时间,如设置失败(一般是因为日期无效),则返回FALSE,如成功则返回TRUEBOOLEAN SystemTime_set(const SYSTEM_TIME *val);// 验证时间是否有效,有效则返回TRUEBOOLEAN SystemTime_Valid(const SYSTEM_TIME *val);// 赋值为NULL;void SystemTime_setNull(SYSTEM_TIME *lval);// 计算某年是否是闰年#define isLeapYear(Year) (Year % 4 == 0 && Year % 100 != 0 || Year % 400 == 0)/*********************************************************************************************************** EVENT 事件**********************************************************************************************************/// 要注意,各事件都是由调用Systemtime_Tick_Signal()的函数内调用的,一般是中断服务程序中// 事件中的传入参数为本地系统时间,只读// 用法:声明个SYSTEM_TIME_EVENT类型的函数,然后赋值给对应事件#pragma DATA_SEG DEFAULTextern SYSTEM_TIME_EVENT SystemTime_onMSecondInc;extern SYSTEM_TIME_EVENT SystemTime_onSecondInc;extern SYSTEM_TIME_EVENT SystemTime_onMinuteInc;extern SYSTEM_TIME_EVENT SystemTime_onHourInc;extern SYSTEM_TIME_EVENT SystemTime_onDayInc;extern SYSTEM_TIME_EVENT SystemTime_onMonthInc;extern SYSTEM_TIME_EVENT SystemTime_onYearInc;/*********************************************************************************************************** FUNCTION PROTOTYPES 函数原型**********************************************************************************************************/// 对外接口,需要被外部定时调用来通知系统时间增加1ms// 调用时要保证执行过程中不会发生中断(比如禁止中断嵌套并在中断中调用)void Systemtime_Tick_Signal(void);/*********************************************************************************************************** ERROR CHECK 错误检查**********************************************************************************************************/#if (SYSTEM_TIME_DEFAULT_YEAR < 0) #error "year must bigger than 0!"#endif#if (SYSTEM_TIME_DEFAULT_MONTH <= 0 || SYSTEM_TIME_DEFAULT_MONTH >= 13) #error "month must between 1 and 12!"#endif#if (SYSTEM_TIME_DEFAULT_DAY <= 0 || SYSTEM_TIME_DEFAULT_DAY >= 32) #error "day must between 1 and 31!"#endif#if (SYSTEM_TIME_DEFAULT_HOUR < 0 || SYSTEM_TIME_DEFAULT_HOUR >= 24) #error "hour must between 0 and 23!"#endif#if (SYSTEM_TIME_DEFAULT_MINUTE < 0 || SYSTEM_TIME_DEFAULT_MINUTE >= 60) #error "minute must between 0 and 59!"#endif#if (SYSTEM_TIME_DEFAULT_SECOND < 0 || SYSTEM_TIME_DEFAULT_SECOND >= 60) #error "second must between 0 and 59!"#endif#if (SYSTEM_TIME_DEFAULT_MSECOND < 0 || SYSTEM_TIME_DEFAULT_MSECOND >= 1000) #error "millsecond must between 0 and 999!"#endif#endif
/************************************************************************************************************* Systemtime SUPPORT PACKAGE* 系统时间支持包** File : SystemTime.c* By : Lin Shijun* Date : 2017/07/20* version: 1.0.0**********************************************************************************************************//*********************************************************************************************************** INCLUDES**********************************************************************************************************/#include <stddef.h>#include "SystemTime.h"/*********************************************************************************************************** EVENT VARIABLE**********************************************************************************************************/#pragma DATA_SEG DEFAULT#if (SYSTEM_TIME_EVENT_ONMSECONDINC_EN == TRUE) SYSTEM_TIME_EVENT SystemTime_onMSecondInc = NULL;#endif #if (SYSTEM_TIME_EVENT_ONSECONDINC_EN == TRUE) SYSTEM_TIME_EVENT SystemTime_onSecondInc = NULL;#endif #if (SYSTEM_TIME_EVENT_ONMINUTEINC_EN == TRUE) SYSTEM_TIME_EVENT SystemTime_onMinuteInc = NULL;#endif#if (SYSTEM_TIME_EVENT_ONHOURINC_EN == TRUE) SYSTEM_TIME_EVENT SystemTime_onHourInc = NULL;#endif#if (SYSTEM_TIME_EVENT_ONDAYINC_EN == TRUE) SYSTEM_TIME_EVENT SystemTime_onDayInc = NULL;#endif#if (SYSTEM_TIME_EVENT_ONMONTHINC_EN == TRUE) SYSTEM_TIME_EVENT SystemTime_onMonthInc = NULL;#endif#if (SYSTEM_TIME_EVENT_ONYEARINC_EN == TRUE) SYSTEM_TIME_EVENT SystemTime_onYearInc = NULL;#endif /*********************************************************************************************************** LOCAL FUNCTION PROTOTYPE**********************************************************************************************************/// 内部使用,对本地系统时间各种单位的自增运算static void _SystemTime_incMSecond(void);static void _SystemTime_incSecond(void);static void _SystemTime_incMinute(void);static void _SystemTime_incHour(void);static void _SystemTime_incDay(void);static void _SystemTime_incMonth(void);static void _SystemTime_incYear(void);/*********************************************************************************************************** LOCAL CONST**********************************************************************************************************/#pragma CONST_SEG DEFAULTstatic const INT8U daytab[2][13] = { { 0,31,28,31,30,31,30,31,31,30,31,30,31 }, { 0,31,29,31,30,31,30,31,31,30,31,30,31 }};#pragma CONST_SEG DEFAULTstatic const SYSTEM_TIME time_Null = { 0,0,0,0,0,0,0};#pragma CONST_SEG DEFAULTconst SYSTEM_TIME* const TimeNull = &time_Null;/*********************************************************************************************************** LOCAL VARIABLE**********************************************************************************************************///#pragma DATA_SEG __NEAR_SEG DEFAULT#pragma DATA_SEG DEFAULT// 当前MCU的系统时间static SYSTEM_TIME LocalTime ={ SYSTEM_TIME_DEFAULT_YEAR, SYSTEM_TIME_DEFAULT_MONTH, SYSTEM_TIME_DEFAULT_DAY, SYSTEM_TIME_DEFAULT_HOUR, SYSTEM_TIME_DEFAULT_MINUTE, SYSTEM_TIME_DEFAULT_SECOND, SYSTEM_TIME_DEFAULT_MSECOND};#pragma DATA_SEG DEFAULT// 存储当前本地时间是否是闰年。用于加快计算,只在年份变更时重新计算static INT8U leapYearNow = isLeapYear(SYSTEM_TIME_DEFAULT_YEAR);// 重新计算现在是否是闰年#define ReCalculateLeap() leapYearNow = isLeapYear(LocalTime.wYear)/*********************************************************************************************************** PUBLIC FUNCTION**********************************************************************************************************/#pragma CODE_SEG DEFAULTvoid SystemTime_get(SYSTEM_TIME *rst){ #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0; #endif OS_ENTER_CRITICAL(); *rst = LocalTime; OS_EXIT_CRITICAL(); return;}BOOLEAN SystemTime_set(const SYSTEM_TIME *val){ #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0; #endif if(SystemTime_Valid(val)){ OS_ENTER_CRITICAL(); LocalTime = *val; OS_EXIT_CRITICAL(); return TRUE; } return FALSE;}BOOLEAN SystemTime_Valid(const SYSTEM_TIME *val){ INT8U leap; if(val->wHour >= 24 || val->wMinute >= 60 || val->wSecond >= 60 || val->wMSecond >= 1000 || val->wMonth >= 13 || val->wMonth == 0 || val->wDay == 0) return FALSE; leap = isLeapYear(val->wYear); if(val->wDay > daytab[leap][val->wMonth]) return FALSE; return TRUE;}void SystemTime_setNull(SYSTEM_TIME *lval){ memcpy(lval,TimeNull,sizeof(SYSTEM_TIME));}/************************************************************************************************************************** SIGNAL THAT IT'S TIME TO UPDATE THE SYSTEMTIME** Description: This function is typically called by the ISR that occurs at the timer tick rate and is used to signal* the systemtime module to update.** Arguments : none** Returns : *************************************************************************************************************************/#pragma CODE_SEG __NEAR_SEG DEFAULTvoid Systemtime_Tick_Signal(void){ _SystemTime_incMSecond();}/*********************************************************************************************************** LOCAL FUNCTION**********************************************************************************************************/#pragma CODE_SEG __NEAR_SEG DEFAULTstatic void _SystemTime_incMSecond(void){ if(++LocalTime.wMSecond >= 1000){ LocalTime.wMSecond = 0; _SystemTime_incSecond(); } #if (SYSTEM_TIME_EVENT_ONMSECONDINC_EN == TRUE) if(SystemTime_onMSecondInc != NULL) SystemTime_onMSecondInc(&LocalTime); #endif }#pragma CODE_SEG __NEAR_SEG DEFAULTstatic void _SystemTime_incSecond(void){ if(++LocalTime.wSecond >= 60){ LocalTime.wSecond = 0; _SystemTime_incMinute(); } #if (SYSTEM_TIME_EVENT_ONSECONDINC_EN == TRUE) if(SystemTime_onSecondInc != NULL) SystemTime_onSecondInc(&LocalTime); #endif}#pragma CODE_SEG DEFAULTstatic void _SystemTime_incMinute(void){ if(++LocalTime.wMinute >= 60){ LocalTime.wMinute = 0; _SystemTime_incHour(); } #if (SYSTEM_TIME_EVENT_ONMINUTEINC_EN == TRUE) if(SystemTime_onMinuteInc != NULL) SystemTime_onMinuteInc(&LocalTime); #endif }static void _SystemTime_incHour(void){ if(++LocalTime.wHour >= 24){ LocalTime.wHour = 0; _SystemTime_incDay(); } #if (SYSTEM_TIME_EVENT_ONHOURINC_EN == TRUE) if(SystemTime_onHourInc != NULL) SystemTime_onHourInc(&LocalTime); #endif }static void _SystemTime_incDay(void){ if(++LocalTime.wDay > daytab[leapYearNow][LocalTime.wMonth]){ LocalTime.wDay = 1; _SystemTime_incMonth(); } #if (SYSTEM_TIME_EVENT_ONDAYINC_EN == TRUE) if(SystemTime_onDayInc != NULL) SystemTime_onDayInc(&LocalTime); #endif}static void _SystemTime_incMonth(void){ if(++LocalTime.wMonth > 12){ LocalTime.wMonth = 1; _SystemTime_incYear(); } #if (SYSTEM_TIME_EVENT_ONMONTHINC_EN == TRUE) if(SystemTime_onMonthInc != NULL) SystemTime_onMonthInc(&LocalTime); #endif}static void _SystemTime_incYear(void){ ++LocalTime.wYear; // 重计算当前是否是闰年 ReCalculateLeap(); #if (SYSTEM_TIME_EVENT_ONYEARINC_EN == TRUE) if(SystemTime_onYearInc != NULL) SystemTime_onYearInc(&LocalTime); #endif}
目前版本只是最简单的实现,提供时间检查,系统时间递增,赋\取,而且递增还是必须1ms的,等以后有需要了再添加其他功能。
如嫌时间的结构体占的空间太大,其实可以把年以外的都改成INT8U。
要记得在适当的地方调用void Systemtime_Tick_Signal(void);以驱动系统时间模块。如在uC/OS-II中,可以把OSTick间隔设为1ms然后Hook在App_TimeTickHook()上(app_hook.c中),像这样修改:
#if OS_TIME_TICK_HOOK_EN > 0void App_TimeTickHook (void){ #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ OS_CPU_SR cpu_sr = 0; #endif#if (uC_PROBE_OS_PLUGIN > 0) && (OS_PROBE_HOOKS_EN > 0) OSProbe_TickHook();#endif OS_ENTER_CRITICAL(); // 通知系统时间模块,当前时间+1ms Systemtime_Tick_Signal(); OS_EXIT_CRITICAL();}
当然,该使能的地方要记得使能。具体的就不细讲了。
使用提供的事件可以很方便的监听系统时间的变化,比如在这个项目中我需要每天重新初始化数据包编号,于是我就可以使能系统时间模块的SystemTime_onDayInc事件(SYSTEM_TIME_EVENT_ONDAYINC_EN设为TRUE)。在初始化时挂载事件:
// 挂载天数增加事件 SystemTime_onDayInc = &onDayInc;
然后在发生事件时的回调函数中初始化包编号:
static void onDayInc(const SYSTEM_TIME *time){ PacketNum = 0;}
然后调用接口获取及设置系统时间什么的都是C语言基本的东西,就不细讲了。
最后,既然读者有需要这个函数,那也有可能需要这个小工具。
【小工具】日期与一年中第几天的转换程序
OK就到这里吧,以后再慢慢改进。
- 【小工具】系统时间SYSTEMTIME 轻量实现
- 开机时间小工具
- 用 Swift 实现轻量的属性监听系统
- 代码量统计小工具V1.0
- 计算java 代码量的小工具
- date 时间转化小工具
- 【小工具】获取当前时间
- 时间转换小工具类
- 清除系统的小工具
- IOS系统降级小工具
- Win7系统截图小工具
- Windows系统时间(FILETIME和SYSTEMTIME)
- Windows系统时间(FILETIME和SYSTEMTIME)
- Windows系统时间(FILETIME和SYSTEMTIME)
- Windows系统时间(FILETIME和SYSTEMTIME)
- 构建轻量消息传递系统
- 多线程检测服务器响应时间小工具
- 时间戳,字符串转换小工具
- strstr函数模拟实现
- 【Maven】Maven POM配置详解
- JDBC(7)—DAO
- WebGIS学习(七)WebGIS中栅格、矢量图层设计之栅格、矢量图层的本质
- 文件下载之断点续传(客户端与服务端的实现)
- 【小工具】系统时间SYSTEMTIME 轻量实现
- CRM的dev(总结)--多思考,先实现,再优化!
- WebGIS学习(八)WebGIS中栅格图层的设计
- HDU-3436 Queue-jumpers(Splay树)
- 谜题3:Long Division 长整除
- 关于quartz调度器
- WebGIS学习(九)WebGIS中的矢量查询(针对AGS和GeoServer)
- 用sflow玩儿转 共享专线带宽占用情况
- 移动端学习笔记(一)