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; // 获取min
						n++;
						break;
				}
				case 6:  
				{
					    val = atoi(str);				
						p_bat->date.tm_sec=val; // 获取min
						n++;
						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的这个模组。

  • 25
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Keil-MDK是一种嵌入式软件开发工具,可以兼容STM32F4系列芯片的支持库。 STM32F4系列芯片是意法半导体推出的一款高性能微控制器系列,内含ARM Cortex-M4内核。这些芯片广泛应用于各种领域的嵌入式系统开发。Keil-MDK中的支持库为开发者提供了简化开发流程、减少编程工作量的便利。 Keil-MDK中的支持库可以帮助开发者通过抽象的接口,快速访问STM32F4系列芯片的功能和外设。通过这些支持库,开发者可以方便地使用芯片上的GPIO口、定时器、USART、ADC等外设,而无需深入了解底层硬件细节。支持库还提供了一些高级功能,如中断控制、DMA等,可加快开发进度。 Keil-MDK中的支持库具有高度可移植性,支持不同型号的STM32F4芯片。通过简单的配置,开发者可以轻松选择合适的芯片型号,并利用相同的代码在不同的芯片上进行开发。这种可移植性大大简化了嵌入式系统的开发过程,提高了开发效率。 总之,Keil-MDK中的STM32F4系列芯片支持库为开发者提供了通用的接口和功能,简化了嵌入式系统的开发流程,提高了开发效率。开发者可以轻松地利用这些库进行芯片的驱动开发和应用程序的编写。 ### 回答2: Keil MDK是一款开发软件,适用于基于ARM Cortex-M内核的微控制器。在Keil MDK中,有一个支持库可以帮助开发者更加方便地使用STM32F4系列芯片。 STM32F4系列芯片是由STMicroelectronics开发的一款微控制器,该系列芯片采用了ARM Cortex-M4内核,具有强大的处理能力和丰富的外设资源。而Keil MDK中的支持库,专门针对STM32F4系列芯片进行了优化和适配。 通过使用Keil MDK中的STM32F4系列支持库,开发者可以方便地访问芯片的各种外设,如GPIO、USART、SPI、I2C等,并进行相关配置和控制。此外,支持库还提供了丰富的API函数,大大简化了开发过程,使开发者可以更加高效地编写代码。 Keil MDK中的STM32F4系列支持库还提供了相应的驱动程序,可以帮助开发者快速启动项目并进行调试。同时,支持库还包含了一些实用工具和示例代码,可以帮助开发者更好地理解和应用芯片的功能。 总之,Keil MDK中的STM32F4系列支持库为开发者提供了丰富的工具和资源,使他们能够更加轻松地开发基于STM32F4系列芯片的应用程序。无论是初学者还是有经验的开发者,都可以通过使用这个支持库,快速、高效地实现自己的项目。 ### 回答3: Keil MDKKeil公司开发的嵌入式软件开发工具,主要用于ARM处理器的软件开发。STM32F4系列是意法半导体公司推出的一款高性能的32位微控制器系列,它们在Keil MDK中具备完整的支持库。 在Keil MDK中,STM32F4系列芯片支持库提供了丰富的软件资源,以帮助开发人员进行STM32F4系列芯片的开发工作。这些支持库包括了各种驱动程序、函数库和例程,以支持各种外设的操作和功能实现。 首先,STM32F4系列芯片支持库提供了标准外设驱动程序,包括GPIO、USART、SPI、I2C、ADC等,这些驱动程序简化了对外设的配置和控制,使开发者可以更加方便地使用这些外设,并且提高了开发效率。 其次,STM32F4系列芯片支持库中还包括了各种函数库,例如操作系统(RTOS)支持库、射频(RF)支持库、USB支持库等。这些函数库提供了丰富的功能接口,使开发者可以直接调用这些接口来实现相应的功能,从而避免了重复编写代码的工作。 另外,STM32F4系列芯片支持库中还提供了大量的应用实例和示例代码,这些代码可以帮助开发者更好地理解和使用STM32F4系列芯片的各种功能。通过参考这些示例代码,开发者可以快速上手,减少开发周期。 总之,Keil MDK中的STM32F4系列芯片支持库为开发者提供了丰富的软件资源,使得开发者能够更加便捷地进行STM32F4系列芯片的软件开发工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HHONGQI123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值