STM32 rtc唤醒 低功耗待机模式 避免iwdog看门狗方案

我们知道stm32f103有很好的低功耗模式,可以使用rtc的闹钟用于定时的唤醒。但很难在IWDOG的使用情况下,设置低功耗。我为了处理这个问题,我们需要设置掉电标志位,因为stm32复位重启后看门狗会失效,在配置看门狗前去检查低功耗标志是否使能,如果使能则直接进入低功耗。从而避免了看门狗的重启困扰。BKP区域用于掉电标志非常安全合适。

直接上代码(测试板子stm32f103)

首先是rtc.c文件,包含掉电备用数据读写(BKP区域用作设置掉电标志位最合适了,有20个16位寄存器),RTC时钟初始化函数,时间设置函数,开机检测是否闹钟唤醒函数,配置开启低功耗模式函数

rtc.c文件

#include "rtc.h"
#define PWR_BackupAccessCmd_ENABLE() 	{RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE); PWR_BackupAccessCmd(ENABLE);}//开启备份区域写入权限	和 配置时钟
#define PWR_BackupAccessCmd_DISABLE() 	{PWR_BackupAccessCmd(DISABLE);}																		//关闭备份区域写入权限

/* 写BKP寄存器 */
void PWR_BackupAccessCmd_WRITE(uint16_t BKP_DR, uint16_t DataA){ 
	PWR_BackupAccessCmd_ENABLE();//开启备份区域写入权限	
	BKP_WriteBackupRegister(BKP_DR, DataA);
	PWR_BackupAccessCmd_DISABLE();//关闭备份区域写入权限
}
/* RTC时钟初始化函数 */
void RCC_Config(void){//时间配置函数
PWR_BackupAccessCmd_ENABLE();	//开启备份区域写入权限		
	if(BKP_ReadBackupRegister(ADDR_RTC) != RTC_ENABLE){			  	//检查用户标志
		/* 配置晶振 */
		RCC_LSEConfig(RCC_LSE_ON);														/* 使能LSE */ 
		while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {} 							/* 等待启动完成 */
		RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);											/* 将 RTC时钟设置为LSE这个32.768KHZ的晶振*/ 
		/* 同步数据 */
		RCC_RTCCLKCmd(ENABLE);															/* 使能RTC Clock */ 
		RTC_WaitForSynchro();															/* 等待同步 */        
		RTC_WaitForLastTask();															/* 等待对RTC寄存器最后的写操作完成*/   
		/* 配置分频 */
		RTC_SetPrescaler(32767);  									//设置了预分频值: 设置RTC时钟周期为1s *//* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1)
		RTC_WaitForLastTask(); 				
		/* 配置标识 */	
		BKP_WriteBackupRegister(ADDR_RTC, RTC_ENABLE);
	}else{
		/* 同步数据 */
		RTC_WaitForSynchro();															/* 等待同步 */        
		RTC_WaitForLastTask();															/* 等待对RTC寄存器最后的写操作完成*/   
	}
PWR_BackupAccessCmd_DISABLE();	//关闭备份区域写入权限	
}

/* 时间设置函数 */
void RTC_Set(uint32_t time){
	if(BKP_ReadBackupRegister(ADDR_RTC) == RTC_ENABLE){			//检查用户标志
PWR_BackupAccessCmd_ENABLE();	//开启备份区域写入权限
		RTC_SetCounter(time);    								//设置RTC初始值
		RTC_WaitForLastTask();		
PWR_BackupAccessCmd_DISABLE();	//关闭备份区域写入权限
	}
}

/* 开机检测是否闹钟唤醒 */
void STD_RESET_START(void){
	if(BKP_ReadBackupRegister(ADDR_RTC) == RTC_ENABLE&&BKP_ReadBackupRegister(ADDR_STD) == RTC_ENABLE){
		u32 STD_time = (BKP_ReadBackupRegister(ADDR_STD_TIME1)<<16)+BKP_ReadBackupRegister(ADDR_STD_TIME2);//获取STD时间
		if(STD_time > (RTC_GetCounter()+5) && GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == 0){
PWR_BackupAccessCmd_ENABLE();	//开启备份区域写入权限			
			/* 中断配置 */
			RTC_ITConfig(RTC_IT_ALR, ENABLE);	
			RTC_WaitForLastTask();	
			/* 闹钟时间配置 */
			RTC_SetAlarm(STD_time);			
			RTC_WaitForLastTask();	
PWR_BackupAccessCmd_DISABLE();	//关闭备份区域写入权限		
			/* 进入低功耗 */	
			PWR_WakeUpPinCmd(ENABLE);
			RCC_APB2PeriphResetCmd(0X01FC,DISABLE);    						//复位IO口时钟,可选择
			RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);    			//使能PWR外设时钟
			PWR_EnterSTANDBYMode();     						
		}
		PWR_BackupAccessCmd_WRITE(ADDR_STD,RTC_DISABLE);					//配置关闭低功耗模式
	}
}

/* 配置开启低功耗模式 */
void RTC_ALARM_Set(uint32_t time){			
	if(BKP_ReadBackupRegister(ADDR_RTC) == RTC_ENABLE){						//检查用户标志
		PWR_BackupAccessCmd_WRITE(ADDR_STD_TIME1,time>>16);					//
		PWR_BackupAccessCmd_WRITE(ADDR_STD_TIME2,time&0x0000FFFF);			//
		PWR_BackupAccessCmd_WRITE(ADDR_STD,RTC_ENABLE);						//
	}
}

头文件rtc.h

#ifndef __RTC_H
#define __RTC_H
#include "stm32f10x.h"
#define	RTC_ENABLE			(0X5679)
#define	RTC_DISABLE			(0X3265)

#define	ADDR_RTC			BKP_DR1
#define	ADDR_UPDATE			BKP_DR2
#define	ADDR_STD			BKP_DR3
#define	ADDR_STD_TIME1		BKP_DR4
#define	ADDR_STD_TIME2		BKP_DR5
/*   ***   */

#define RTC_Get(x) 			RTC_GetCounter(x)		//时间获取函数
void RTC_Set(uint32_t time);						//时间设置函数
void RTC_ALARM_Set(uint32_t time);					//闹钟设置函数

void RCC_Config(void);								//时间初始化函数
void STD_RESET_START(void);							//低功耗模式检测函数

/* BKP区域 */
void PWR_BackupAccessCmd_WRITE(uint16_t BKP_DR, uint16_t Data);
#endif

下面是测试用main函数

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "rtc.h"
int main(void)
{ 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//设置中断优先级分组2
	delay_init();	    							//延时函数初始化	  
	uart_init(9600);	 							//串口初始化为9600
	RCC_Config();									//时钟初始化函数;
	STD_RESET_START();								//判断是否是低功耗状态
	while(1)
	{
		u32 sss = RTC_Get();
		printf("rtc     = 0x%x\r\n",sss);
		
		RTC_ALARM_Set(sss+20);
		delay_ms(1000);								  
	};  											    
}	

配合weak_up引脚测试唤醒,可以有很好的效果
注意:在每次(PWR_BackupAccessCmd_DISABLE();//关闭备份区域写入权限)后
都需要重新开启时钟,在这里写成宏定义
( PWR_BackupAccessCmd_ENABLE() ;//开启备份区域写入权限 和 配置时钟)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值