KEIL-MDK的时间戳之time.h 结合gd32f1的RTC应用

KEIL-MDK的时间戳之time.h 的应用

1 时间戳介绍

现在物联网产品的在进行通讯的时候,需要加入时间戳的这个信息参数,方便服务器和产品之间交换时间信息。

时间戳是计算机系统中用来表示日期和时间的一种方式,通常是一个数字或者一串字符,表示从某个特定时间点(通常是“纪元”或“起始时间”)开始经过的秒数或者毫秒数。时间戳通常是以协调世界时(UTC)为基准的,但也可以根据需要使用其他时区。

时间戳的优点是它提供了一种统一的方式来表示时间,无论用户所在的时区如何,都可以通过时间戳来精确地表示一个特定的时间点。这在计算机系统中进行时间计算、排序和存储时非常有用。

时间戳通常用于记录事件发生的时间,例如在日志文件中记录系统活动的时间、在数据库中存储数据的创建或修改时间等。它也经常用于计算时间间隔,例如计算两个事件之间经过的时间,或者用于定时任务的调度。

在很多编程语言和操作系统中,时间戳通常是以自某个特定日期开始的秒数来表示,这个特定日期被称为“纪元”(epoch)。UNIX 系统通常使用1970年1月1日作为纪元,而Windows系统则使用1601年1月1日。

KEIL的time文件采用UNIX 系统通常使用1970年1月1日作为纪元。

2 RTC模块介绍

GD32F1系列是基于ARM Cortex-M3内核的通用微控制器系列,由中国的光电半导体(GigaDevice)公司开发。该系列包括了具有丰富外设和功能的微控制器,其中也包括了RTC(Real-Time Clock,实时时钟)模块。

RTC模块是用来提供精确的时间信息的硬件设备,在嵌入式系统中通常用于实现实时时钟、日历功能和时间戳等应用。以下是关于GD32F1系列的RTC模块的一般介绍。

这里以gd32f1的RTC为例。 gd32f1的集成了一个RTC的模组,可以非常方便自动记录时间。

2.1 电路设计

为了达到比较精确的时间记录,为RTC增加了一个32.768kHz的晶振。 这样比较保存时间。
在这里插入图片描述
在这里插入图片描述

2.2 驱动代码开发

开发RTC(Real-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:29+32"  "07/10/25,11:33:44+08"
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 n=1;int val;for( str=strtok(arr, sep);str!=NULL;str=strtok(NULL,sep)){switch(n){case 1:  {val = atoi(str);if(val !=0){p_bat->date.tm_year=val+2000; // 获取年n++;break;}else{return 2;  // 解析错误}}case 2:  {val = atoi(str);				p_bat->date.tm_mon=val; // 获取月n++;break;}case 3:  {val = atoi(str);				p_bat->date.tm_mday=val; // 获取日n++;break;}case 4:  {val = atoi(str);				p_bat->date.tm_hour=val; // 获取hour					   n++;break;}case 5:  {val = atoi(str);				p_bat->date.tm_min=val; // 获取minn++;break;}case 6:  {val = atoi(str);				p_bat->date.tm_sec=val; // 获取minn++;break;}default: break;			}			}if(n<6){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_isdst=0;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_isdst=0;time_t_Set_Time=mktime(&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.timestamp=rtc_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的这个模组。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/678594.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记一次deepin开机突然进不了可视化界面,只能进命令行

看见开机报错failed to start file system on /dev/disk/by-uid/246… 文件系统出现损坏 然后只能在控制台输入密码登录root账号 直接使用这个命令尝试&#xff0c;然后reboot命令重启 fsck /dev/disk/by-uid/246...重启之后又可以进图形化界面了

[优雅的面试] 进程 线程 协程分的清

面试官大佬&#xff1a;小伙子&#xff0c;咱今儿个先聊聊进程线程这块的知识哈&#xff0c;就先说说进程吧。 我&#xff1a;存储在硬盘中的代码是静态文件&#xff0c;运行中的程序被称为进程。进程之间数据是相互隔离的。 一般说来&#xff0c;一个进程并不是自始至终连续不…

Vits2.3-Extra-v2:中文特化,如何训练及推理(新手教程)

环境&#xff1a; Vits2.3-Extra-v2:中文特化修复版 auto_DataLabeling 干声10分钟左右.wav 问题描述&#xff1a; Vits2.3-Extra-v2:中文特化&#xff0c;如何训练及推理&#xff08;新手教程&#xff09; 解决方案&#xff1a; 一、准备数据集 切分音频 本次音频数据…

管理就是闭环

管理是什么&#xff1f;这个问题没有一个统一的答案。本文提供一个管中窥豹的答案&#xff1a;管理就是闭环。 作为基层管理者&#xff0c;日常管理事务&#xff0c;一个是目标闭环&#xff0c;一个是执行闭环。这分别对应敏捷PO和Scrum Master的职责。PO的职责是确保目标闭环&…

vue3学习——router-view 过渡动画

虽然vue3说建vue页面不用包裹一个根节点&#xff0c;但是transition不能没有唯一的标签 所以还是得包一层~ o(&#xffe3;▽&#xffe3;)o <el-main><router-view v-slot"{ Component, route }"><transition name"MainFade" mode"o…

猫头虎分享已解决Bug ‍ || TypeError: props is not a function (React)

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

linux赋予普通用户权限

当我们在Linux系统中操作文件或目录时&#xff0c;有时候会遇到权限的问题。为了正确管理文件和目录的所有权&#xff0c;我们可以使用sudo chown命令。在本文中&#xff0c;我将介绍这个命令以及它的一个示例用法。 什么是sudo chown命令&#xff1f; sudo chown是Linux系统…

【Vue项目】filters过滤器

在vue项目中需要对一些数据进行格式化&#xff0c;我们可以通过Vue.filter进行过滤 Vue.filter 过滤器在 Vue 实例中使用 Vue.filter 方法进行注册&#xff0c;注册成功就可以在任何 Vue模板中使用这些过滤器来对数据进行处理和格式化。 Vue项目中&#xff0c;过滤器可以在全…

05.坐标系

1. 坐标系原点 坐标系原点就是屏幕/窗口的左上角&#xff0c;X向右增长&#xff0c;Y向下增长。 2.设置控件位置 设置控件位置&#xff0c;就相当于是需要指定控件的坐标&#xff0c;对于该控件来说&#xff0c;其坐标原点是其父窗口/父控件的左上角。 设置方法就是通过控件的…

创新S3存储桶检索:Langchain社区S3加载器搭载OpenAI API

在瞬息万变的数据存储和处理领域&#xff0c;将高效的云存储解决方案与先进的 AI 功能相结合&#xff0c;为处理大量数据提供了一种变革性的方法。本文演示了使用 MinIO、Langchain 和 OpenAI 的 GPT-3.5 模型的实际实现&#xff0c;重点总结了存储在 MinIO 存储桶中的文档。 …

leetcode:62.不同路径

动态规划 注意&#xff1a;用深搜或者广搜会超时 dp含义dp[i,j]&#xff1a;从&#xff08;0&#xff0c;0&#xff09;到&#xff08;i&#xff0c;j&#xff09;的路径个数 递推公式&#xff1a;dp[i][j] dp[i-1][j] dp[i][j-1] 初始化&#xff1a;for(i 0,i<m,i) …

[职场] 面试被问优点的回答参考 #知识分享#其他#学习方法

面试被问优点的回答参考 当面试官问你最大的优点是什么&#xff1f;回答1&#xff1a; 我擅长合理地安排时间&#xff0c; 作为助理&#xff0c; 我的杂事很多&#xff0c; 总是觉得手边有做不完的事情&#xff0c; 所以我特别注意时间管理&#xff0c; 这样才能高效地工作&am…

继承

1.继承的作用 有些类与类之间存在特殊关系&#xff0c;下级别的成员除了拥有上一级别的共性&#xff0c;还有自己的特性。 这个时候我们就可以考虑利用继承技术&#xff0c;减少重复代码。 总结&#xff1a; 继承的好处&#xff1a;可以减少重复的代码 class A : public B;…

猫头虎分享已解决Bug || KeyError: ‘The truth value of a Series is ambiguous‘

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

并发事务带来的问题及解决方法

引言 在数据库系统中&#xff0c;事务是指一组操作被视为一个逻辑单元&#xff0c;要么全部执行成功&#xff0c;要么全部不执行&#xff0c;保证数据库的一致性和完整性。而并发事务则是指多个事务同时执行的情况。虽然并发事务能够提高系统的性能和吞吐量&#xff0c;但也会…

EasyExcel动态列导出

测试代码地址&#xff1a;https://gitee.com/wangtianwen1996/cento-practice/tree/master/src/test/java/com/xiaobai/easyexcel/dynamiccolumn 官方文档&#xff1a;https://easyexcel.opensource.alibaba.com/docs/2.x/quickstart/write 一、实现方式 1、根据需要导出的列…

假期刷题打卡--Day26

1、MT1212乘法表 请编写一个简单程序&#xff0c;输出九九乘法表。输入n&#xff0c;就输出乘法表到n的地方。 格式 输入格式&#xff1a; 输入整型 输出格式&#xff1a; 输出整型。形式如&#xff1a;1*11 样例 1 输入&#xff1a; 5输出&#xff1a; 1*11 2*12 …

vue3项目中的404页面

vue3项目中的404页面 春节前的最后一篇技术博客了 写了不少vue项目&#xff0c;发现一直没有正确处理404页面。404页面的出现有这么几种可能&#xff1a; 错误输入了页面地址路由连接跳转时&#xff0c;某些路由已经不存在了&#xff0c;而程序员并没有正确处理 也就是说40…

effective c++ 笔记 条款13-18

条款13 以对象管理资源 对象的delete&#xff0c;可能因为前文的一些语句抛出异常或者过早的return(可能是最初的设计也可能多个迭代版本之后的维护导致)使得delete并没有执行&#xff0c;导致内存泄漏。 因此以对象管理资源。并采用RAII&#xff08;Resource Acquisition Is …

Rust基础拾遗--进阶

Rust基础拾遗 前言1.结构体2.枚举与模式3.运算符重载4.迭代器5.集合 前言 通过Rust程序设计-第二版笔记的形式对Rust相关重点知识进行汇总&#xff0c;读者通读此系列文章就可以轻松的把该语言基础捡起来。 1.结构体 2.枚举与模式 3.运算符重载 4.迭代器 5.集合