软件RTC在单片机上的C语言实现(二)

软件RTC在单片机上的C语言实现(二)

一.前言

上一篇文章讲了软件rtc实现的第一种方法,用的是相对天数值,然后通过两个转换函数作为单片机内部系统与现实日期的接口。废话不多说,今天贴第二种实现方法,也是最传统的软件rtc处理方法。

二.实现

2.1 定义结构体类型和变量

typedef struct
{
	u32 minute  :6;  
	u32 hour    :5;
	u32 date    :5;
	u32 month   :4;
	u32 year    :8; 
	u32 weekDay :4;
}ST_RTCDATA;

//rtc值
ST_RTCDATA gs_RtcData;

//列举闰年时候每个月的天数
u8 gs_LeapYearMonDays[12]={31,29,31,30,\
							   31,30,31,31,\
							   30,31,30,31};

//列举平年的时候每个月的天数
u8 gs_OrdYearMonDays[12]={31,28,31,30,\
							  31,30,31,31,\
							  30,31,30,31};
//秒值							  
u8 gu8_CurSecond;

//rtc是否完成了初始化,当获取到了外部时间且赋值到了gs_RtcData将其更新为1
u8 gu8_RtcInitFlg;

肯定有人会想为什么我定义的这个ST_RTCDATA结构体不包含秒值,为什么要用C语音中的位字段的写法。其实这样写是为了方便rtc值大小的比较。我会在文章后面讲述关于带有时间属性的数据做排序和比较的时候详细介绍。

2.2 软件rtc的时间更迭的实现

//传入当前实际年份减去2000后的值
//闰年返回1,平年返回0
u8 Rtc_IsLeapYear(u8 curYear)
{
	if(curYear%4==0)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
//软件rtc,1s调用一次
void Rtc_Loop(ST_RTCDATA *time)
{
	u8 monthDays=0;

	//时间经过校准后再运行软件rtc
	if(!gu8_RtcInitFlg)
	{
		return;
	}
	
	gu8_CurSecond++;

	if(gu8_CurSecond>=60)
	{
		gu8_CurSecond=0;

		time->minute++;

		if(time->minute>=60)
		{
			time->minute=0;
			time->hour++;

			if(time->hour>=24)
			{
				time->hour=0;
				time->date++;

				time->weekDay++;
				
				//更新星期值
				if(time->weekDay>7)
				{
					time->weekDay=1;
				}
				
				//获取当前年份月份的天数
				if(Rtc_IsLeapYear(time->year)) //闰年
				{
					monthDays=gs_LeapYearMonDays[time->month-1];
				}	
				else //平年
				{
					monthDays=gs_OrdYearMonDays[time->month-1];
				}

				//如果当前日期大于当前月份的天数了,月份加1,天数置为1
				if(time->date>monthDays)
				{
					time->date=1;
					time->month++;

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C语言编写单片机RTC配置的示例代码,假设使用的是STM32F103单片机: ```c #include "stm32f10x.h" // 包含 STM32F103 系列芯片的头文件 // 定义 RTC 配置函数 void RTC_Configuration(void) { // 使能PWR和BKP外设时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); // 启用备份区域 PWR_BackupAccessCmd(ENABLE); // 检查是否第一次配置RTC if (BKP_ReadBackupRegister(BKP_DR1) != 0x1234) { // 设置RTC时钟源 RCC_LSEConfig(RCC_LSE_ON); while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {} RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); RCC_RTCCLKCmd(ENABLE); // 等待RTC寄存器同步 RTC_WaitForSynchro(); // 设置RTC分频器 RTC_SetPrescaler(32767); // 为LSE时钟源设置RTC分频器,使得每秒钟RTC时钟为32768个计数值。因为 LSE 的频率为32.768kHz。 // 设置RTC初始时间 RTC_SetCounter(0); RTC_SetAlarm(10); RTC_WaitForLastTask(); // 将配置信息写入备份寄存器 BKP_WriteBackupRegister(BKP_DR1, 0x1234); } } ``` 该示例代码实现了以下功能: 1. 启用PWR和BKP外设时钟。 2. 启用备份区域。 3. 检查是否第一次配置RTC,若是,则进行RTC的初始化配置。 4. 设置RTC时钟源为LSE(外部低速振荡器)。 5. 等待LSE稳定,启用RTC时钟。 6. 设置RTC分频器,使得每秒钟RTC时钟为32768个计数值。 7. 设置RTC初始时间(这里设置为0秒),并设置一个闹钟(10秒后触发)。 8. 将配置信息写入备份寄存器。 需要注意的是,该示例代码中使用的是外部低速振荡器(LSE)作为RTC时钟源。如果使用其他时钟源,需要相应地修改代码。同时,需要根据实际需求修改RTC初始时间和闹钟触发时间。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值