东莞桂城网站建设,建站行业最新消息,淘宝付费推广,dw网页制作成品代码加图片KEIL-MDK的时间戳之time.h 的应用
1 时间戳介绍
现在物联网产品的在进行通讯的时候#xff0c;需要加入时间戳的这个信息参数#xff0c;方便服务器和产品之间交换时间信息。
时间戳是计算机系统中用来表示日期和时间的一种方式#xff0c;通常是一个数字或者一串字符需要加入时间戳的这个信息参数方便服务器和产品之间交换时间信息。
时间戳是计算机系统中用来表示日期和时间的一种方式通常是一个数字或者一串字符表示从某个特定时间点通常是“纪元”或“起始时间”开始经过的秒数或者毫秒数。时间戳通常是以协调世界时UTC为基准的但也可以根据需要使用其他时区。
时间戳的优点是它提供了一种统一的方式来表示时间无论用户所在的时区如何都可以通过时间戳来精确地表示一个特定的时间点。这在计算机系统中进行时间计算、排序和存储时非常有用。
时间戳通常用于记录事件发生的时间例如在日志文件中记录系统活动的时间、在数据库中存储数据的创建或修改时间等。它也经常用于计算时间间隔例如计算两个事件之间经过的时间或者用于定时任务的调度。
在很多编程语言和操作系统中时间戳通常是以自某个特定日期开始的秒数来表示这个特定日期被称为“纪元”epoch。UNIX 系统通常使用1970年1月1日作为纪元而Windows系统则使用1601年1月1日。
KEIL的time文件采用UNIX 系统通常使用1970年1月1日作为纪元。
2 RTC模块介绍
GD32F1系列是基于ARM Cortex-M3内核的通用微控制器系列由中国的光电半导体GigaDevice公司开发。该系列包括了具有丰富外设和功能的微控制器其中也包括了RTCReal-Time Clock实时时钟模块。
RTC模块是用来提供精确的时间信息的硬件设备在嵌入式系统中通常用于实现实时时钟、日历功能和时间戳等应用。以下是关于GD32F1系列的RTC模块的一般介绍。
这里以gd32f1的RTC为例。 gd32f1的集成了一个RTC的模组可以非常方便自动记录时间。
2.1 电路设计
为了达到比较精确的时间记录为RTC增加了一个32.768kHz的晶振。 这样比较保存时间。
2.2 驱动代码开发
开发RTCReal-Time Clock实时时钟驱动代码的配置思路如下
选择合适的时钟源
RTC通常需要一个稳定的时钟源来提供时间基准。这可以是外部晶振或者内部RC振荡器。在配置RTC之前需要确定使用哪种时钟源并相应地配置系统时钟。 初始化RTC模块
首先需要初始化RTC模块包括启用RTC时钟、选择时钟源、配置分频系数等。这通常涉及设置RTC相关的寄存器具体操作可参考MCU的技术手册。 设置时间
在RTC初始化后需要设置当前时间。这可以通过设置RTC的年、月、日、时、分、秒等寄存器来完成。一般情况下需要提供一个函数接口允许用户设置初始时间。 配置闹钟功能可选
如果需要使用RTC的闹钟功能需要配置相应的闹钟寄存器。这包括设置闹钟触发时间、选择触发模式例如每秒、每分钟、每小时等、启用闹钟中断等。 处理RTC中断
如果RTC模块支持中断功能需要编写中断服务程序ISR来处理RTC中断。这可能涉及到处理时间更新中断、闹钟触发中断等。在中断服务程序中通常需要清除相应的中断标志位。 备份寄存器的使用可选
一些MCU的RTC模块提供了备份寄存器用于在系统掉电时保存特定的数据。如果需要使用备份寄存器需要相应地初始化和配置备份寄存器。 测试与调试
完成RTC驱动代码后需要进行测试和调试。可以使用仿真器或者实际硬件进行测试并检查RTC功能是否按预期工作。 优化与稳定性提升
在测试过程中可以对RTC驱动代码进行优化提高代码的稳定性和性能。例如考虑使用更有效率的算法或者减少对寄存器的访问次数来优化代码。 通过以上步骤可以完成对RTC模块的驱动代码配置实现所需的实时时钟功能并确保代码的可靠性和稳定性。
void rtc_configuration(void)
{/* enable PMU and BKPI clocks */rcu_periph_clock_enable(RCU_BKPI);rcu_periph_clock_enable(RCU_PMU);/* allow access to BKP domain */pmu_backup_write_enable();/* reset backup domain */bkp_deinit();/* enable LXTAL */rcu_osci_on(RCU_LXTAL);/* wait till LXTAL is ready */rcu_osci_stab_wait(RCU_LXTAL);/* select RCU_LXTAL as RTC clock source */rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);/* enable RTC Clock */rcu_periph_clock_enable(RCU_RTC);/* wait for RTC registers synchronization */rtc_register_sync_wait();/* wait until last write operation on RTC registers has finished */rtc_lwoff_wait();// /* enable the RTC second interrupt*/
// rtc_interrupt_enable(RTC_INT_SECOND);// /* wait until last write operation on RTC registers has finished */
// rtc_lwoff_wait();/* set RTC prescaler: set RTC period to 1s */rtc_prescaler_set(32767);/* wait until last write operation on RTC registers has finished */rtc_lwoff_wait();
}3 字符串转化成为时间戳
将字符串转换为时间戳的过程通常需要以下步骤具体实现方式取决于所用编程语言和库
解析字符串首先需要解析输入的字符串提取其中的年、月、日、时、分、秒等时间信息。这可能需要使用字符串处理函数或正则表达式来提取有效的时间信息。
转换为结构化时间将提取出的时间信息转换为结构化时间即包含年、月、日、时、分、秒等字段的时间数据结构。不同编程语言和库提供了不同的函数或类来表示结构化时间。
转换为时间戳最后将结构化时间转换为时间戳即从某个特定时间点通常是纪元时间如1970年1月1日开始的秒数或毫秒数。通常可以使用编程语言提供的时间转换函数来实现这一步骤。
具体实现步骤
3.1 字符串转化成为年、月、日、时、分、秒等时间信息
// 时间字符串转化成为时间 19/05/29,02:05:2932 07/10/25,11:33:4408
int DateString_to_TM(Bat_Struct *p_bat)
{if(rt_strncmp(p_bat-rtcstr,\0,2)0) // 判断输入不为空{return 1; // 输入错误}else{
// struct tm myTime {0}; char arr[32];strcpy(arr,p_bat-rtcstr); // 复制数据rt_kprintf(arr is %s\r\n,arr);const char * sep /,:; // 分割符号char *str NULL; uint32_t n1;int val;for( strstrtok(arr, sep);str!NULL;strstrtok(NULL,sep)){switch(n){case 1: {val atoi(str);if(val !0){p_bat-date.tm_yearval2000; // 获取年n;break;}else{return 2; // 解析错误}}case 2: {val atoi(str); p_bat-date.tm_monval; // 获取月n;break;}case 3: {val atoi(str); p_bat-date.tm_mdayval; // 获取日n;break;}case 4: {val atoi(str); p_bat-date.tm_hourval; // 获取hour n;break;}case 5: {val atoi(str); p_bat-date.tm_minval; // 获取minn;break;}case 6: {val atoi(str); p_bat-date.tm_secval; // 获取minn;break;}default: break; } }if(n6){return 2; // 解析错误} else{return 0; // 成功}}
}3.2 利用mktime变成时间戳同时考虑时区问题。
其中tm_diff 用来调整时区北京时区是东八区
uint32_t time_regulate(int syear,int smon,int sday,int hour,int min,int sec)
{time_t time_t_Set_Time; //定义time_t类型的设置时间结构体struct tm tm_Set_Time; //定义tm结构的设置时间结构体tm_Set_Time.tm_year (uint32_t)(syear-1900); //从1900年开始算起tm_Set_Time.tm_mon (uint32_t)(smon-1); //月tm_Set_Time.tm_mday (uint32_t)sday; //日tm_Set_Time.tm_hour (uint32_t)hour; //时tm_Set_Time.tm_min (uint32_t)min; //分tm_Set_Time.tm_sec (uint32_t)sec; //秒tm_Set_Time.tm_isdst0;struct tm diff;diff.tm_year (uint32_t)(1970-1900); //从1900年开始算起diff.tm_mon 0; //月diff.tm_mday 1; //日diff.tm_hour 8; //时区diff.tm_min 0; //分diff.tm_sec 0; //秒diff.tm_isdst0;time_t_Set_Timemktime(tm_Set_Time)-mktime(diff); // 插入 return time_t_Set_Time; // 存储时间戳}3.3 写入寄存器
把时间戳的值写入到寄存器中可以让RTC电路自动进行累加。 rtc_lwoff_wait();/* change the current time */rtc_counter_set(time_regulate(data-tm_year,data-tm_mon,data-tm_mday,data-tm_hour,data-tm_min,data-tm_sec));/* wait until last write operation on RTC registers has finished */rtc_lwoff_wait();3.4 读取时间戳
sysBat.timestamprtc_counter_get(); // 获取时间戳4 把时间戳变成字符串
// 定义时间戳time_t timestamp 1644202496; // 2024-02-07 12:34:56// 使用localtime函数将时间戳转换为tm结构体struct tm *timeinfo;timeinfo localtime(timestamp);// 使用strftime函数将tm结构体格式化为字符串char buffer[80];strftime(buffer, sizeof(buffer), %Y-%m-%d %H:%M:%S, timeinfo);// 输出格式化后的字符串printf(Formatted date and time: %s\n, buffer);5 总结
RTC的实际使用结合时间戳比较应用价值很多参考案把f1当作只能记录一天时间的读秒器失去这个RTC应用意义。希望这篇文章帮助读者更好应用RTC的这个模组。