解决STM32内部时钟当RTC时钟源计时不准问题(用于精准时间内唤醒处于停止模式下的设备)

因为LSI是RC振荡电路产生,所以产生的时钟周期都不会太准。但是由于很多公司为了节约成本不会选择LSE,当然这也没有问题,只要定时器能正常工作也能够很准的计时。

但是,很多类型的设备例如手持设备,需要做到低功耗,就需要进入停止模式,这时候只有RTC可以运行对芯片进行唤醒。这时候就需要进行精准的进行唤醒(例如:10s唤醒一次)。此时可采用的一种方法是,使用定时器进行校准。

校准函数如下所示:

void RTC_Calibrate(double* m)
{
	u32 timeT3 = 0;
	u32 timeRTC = 0;
	
	RTC_WaitForLastTask();//等待RTC完成设置
	RTC_SetCounter(0);
	RTC_WaitForLastTask();
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
	TIM3->CNT = 0;
	timeT3 = Get_Ticks();//外部函数,每1ms自加1
	
	while(1)
	{
		IWDG->KR = 0xAAAA;

		if(Get_Ticks() - timeT3 >= 500)
		{
			timeRTC = RTC_GetCounter();
			*m = (double)timeRTC / (double)500;//
			break;
		}
	}
}

m的值即为校准之后的值,若需要延时10s

停止模式前和停止模式后加入以下代码:

Sys_Enter_StopMode(m*10);
Sys_Exit_StopMode(m*10);

在你需要进入停止模式时:

void Sys_Enter_StopMode(u32 rtcs)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	u32 remainTime = 0;
	//非关机模式下
	if(rtcs != 0)
	{
		remainTime = rtcs;
		//如果时间大于20s,则先等待20s后再唤醒喂狗后再接着等待,若未开启看门口,可略去
		if(remainTime >= 700000UL)
			remainTime -= 700000UL;
		else
			remainTime = 0;
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);	//使能PWR和BKP外设时钟 
		PWR_BackupAccessCmd(ENABLE);																							//使能后备寄存器访问
		BKP_WriteBackupRegister(REMAIN_TIME_DR_H, (u16)(remainTime >> 16));				//将剩余时间写入后备寄存器中
		BKP_WriteBackupRegister(REMAIN_TIME_DR_L, (u16)(remainTime));		
		if(rtcs >= 700000UL) 
			RTC_SetAlarmTime(700000UL);
		else
			RTC_SetAlarmTime(rtcs);
		
	}
	//一定要打开PWR时钟,否则功耗会增加
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
	//将未使用的IO口初始化为模拟输入,降低功耗,串口脚PA9/PA10需要设置为模拟,不然实测使用内部晶振时连接串口线会导致RTC计数变慢,慢了18个ms左右。没有测试过外部晶振
	// 模拟输入你未使用的GPIO

	//进入停止模式
	PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
}
//当设备被唤醒时,需要对rtcs进行判断

 

当自动退出停止模式时进行判断:

void Sys_Exit_StopMode(u32 rtcs)
{
	u32 remainTime = 0;
	
		while(1)
		{
			remainTime = ((u32)BKP_ReadBackupRegister(REMAIN_TIME_DR_H) << 16) 
                                         + BKP_ReadBackupRegister(REMAIN_TIME_DR_L)       ;			
			if(remainTime == 0)			//唤醒时间,直接唤醒,
			{	
	                   //add your code
                            break;
			}
			else    //每20S喂狗,避免复位
			{
				IWDG_ReloadCounter();
				Sys_Enter_StopMode(remainTime);
			}
		}
	}
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值