AT32F435 定时器Time1实现 实时更新时间(万年历算法)

该项目通过RTC获取时间并利用定时器每40秒更新时间,采用万年历算法处理闰年和平年的天数差异。代码中初始化日期为2023年12月31日,通过主函数配置定时器,中断服务程序更新秒数,当达到40秒时更新日期。
摘要由CSDN通过智能技术生成

一.项目实验的内容

1.从RTC中获取时间,然后利用定时器,定时一段时间去更新时间。

这个更新时间的算法:本人采用的是万年历算法的思想实现的。

2.具体难点:需要判断是否是闰年,闰年与平年的天数不一样。

因为我使用的板子是自己公司做的,RTC电路没有装外部晶振,因此我的代码中 初始日期为 自己设定。

废话不多说,直接上代码。

二.代码实现

①参数定义与头文件引入

#include "at32f435_437_board.h"
#include "at32f435_437_clock.h"

/** @addtogroup AT32F435_periph_examples
  * @{
  */

/** @addtogroup 435_TMR_timer_base TMR_timer_base
  * @{
  */

void Update_time(uint32_t t);

uint32_t time_s = 0;
//假设当前时间为:2023-12-31-23-59-59 (这里的时间可以读取芯片中RTC获取。)
uint32_t year = 2023;
uint32_t month = 12;
uint32_t day = 31;
uint32_t hour = 23;
uint32_t minute = 59;
uint32_t second = 59;
uint32_t yuefen[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
uint32_t yuefen1[12] = {31,29,31,30,31,30,31,31,30,31,30,31};//闰年


crm_clocks_freq_type crm_clocks_freq_struct = {0};//AT32F435时钟结构体,0表示sclk

参数说明,为啥设定2023-12-31-23-59-59,因为想着这个时间比较特殊,涉及到跨年,更容易看出代码有没有问题。

uint32_t time_s = 0 ; 用于定时多长时间,更新一次时间。

②主函数中定时器的配置

int main(void)
{
  system_clock_config();

  at32_board_init();
	
	uart_print_init(115200);

  /* get system clock */
  crm_clocks_freq_get(&crm_clocks_freq_struct);


  /* enable tmr1 clock */
  crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);

  /* tmr1 configuration */
  /* time base configuration */
  tmr_base_init(TMR1, 9999, (crm_clocks_freq_struct.apb2_freq * 2 / 10000) - 1); 
  tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);

  /* overflow interrupt enable */
  tmr_interrupt_enable(TMR1, TMR_OVF_INT, TRUE);

  /* tmr1 hall interrupt nvic init */
  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  nvic_irq_enable(TMR1_OVF_TMR10_IRQn, 1, 0);

  /* enable tmr1 */
  tmr_counter_enable(TMR1, TRUE);

  while(1)
  {
		Update_time(40);//40秒更新一次
	}
}

我们把定时器配置为1秒钟产生一次中断,计数方式是 向上计数。

我设定了40秒钟更新一次时间。

③定时器1中断函数

void TMR1_OVF_TMR10_IRQHandler(void)
{
  if(tmr_flag_get(TMR1, TMR_OVF_FLAG) == SET)
  {
    time_s++;
    tmr_flag_clear(TMR1, TMR_OVF_FLAG);
  }
}

定时器1中断功能:每次产生中断,令time_s加1,直到time_s 等于 40的时候,更新一次时间。

④万年历算法实现时间更新

void Update_time(uint32_t t)
{
	uint32_t days;//天 
	uint32_t hours;//小时 
	uint32_t minutes;//分钟 
	uint32_t seconds;//秒 
	uint32_t i, q;
	uint32_t temp = 0;

	days = time_s/ (24 * 3600);//计算天数,一天24*60*60秒 

	time_s = time_s % (24 * 3600);//当前天的总秒数 
	hours =  time_s / 3600;//计算当前天的小时 
	time_s = time_s % 3600;//分钟的秒数+秒数 
	minutes = time_s / 60;//计算当前天的分钟 
	seconds = time_s % 60;//当前的秒数 
	
	
	if(time_s == t)
	{
			//计算年份 
	for (i = days; i > 364; i--)//天数大于一整年的。
	{
		if (((year % 4 == 0) && (year % 100 != 0)) || year % 400 == 0)//闰年 
		{
			year = year + 1;
			i = i - 366 + 1;
		}
		else {//非闰年 
			year = year + 1;
			i = i - 365 + 1;
		}
	}

	//更新时间
	second = second + seconds;
	if (second >= 60)
	{
		second = second - 60;
		minute++;
	}
	minute = minute + minutes;
	if (minute >= 60)
	{
		minute = minute - 60;
		hour++;
	}
	hour = hour + hours;
	if (hour >= 24)
	{
		hour = hour - 24;
		day++;
	}
	if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)//闰年情况下 更新天数
	{
		day = day + i;
		for (q = month - 1; q < 12; q++)
		{
			temp = yuefen1[q];
			if (temp < day + 1)
			{
				month = month + 1;
				day = day - yuefen1[q];
			}
			else break;
		}
		if (q >= 12 && day > 31)
		{
			for (q = 0; q < 12; q++)
			{
				temp = yuefen1[q];
				if (temp < day + 1)
				{
					month = month + 1;
					day = day - yuefen1[q];
				}
			}
		}
	}
	else
	{
		day = day + i;
		for (q = month - 1; q < 12; q++)
		{
			temp = yuefen[q];
			if (temp < day + 1)
			{
				month = month + 1;
				day = day - yuefen[q];
			}
			else break;
		}
		if (q >= 12 && day > 31)
		{
			for (q = 0; q < 12; q++)
			{
				temp = yuefen[q];
				if (temp < day + 1)
				{
					month = month + 1;
					day = day - yuefen[q];
				}
			}
		}
	}
	if (month > 12)
	{
		month = month - 12;
		year++;
	}
	printf("%d年 %d月 %d日 %d时 %d分 %d秒",year,month,day,hour,minute,second);
	time_s = 0;
	}

}

具体的逻辑自己去想一想 也能 想出来。

三、仿真效果。

用printf函数通过串口打印出来,通过串口调试助手可以观察到仿真效果。

 完美定时40秒 更新一次时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值