本文章基于STM32F103RC;
在开启独立看门狗的状态下,进入停机模式,由RTC定时闹钟唤醒系统。
直接上代码:
#include "main.h"
static void RTC_NVIC_Config(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn; //RTC闹钟中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级1位
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //先占优先级0位
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能该通道中断
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
//
//闹钟中断接到第17线外部中断
EXTI_ClearITPendingBit(EXTI_Line17);
EXTI_InitStructure.EXTI_Line = EXTI_Line17;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
//实时时钟配置
//初始化RTC时钟,同时检测时钟是否工作正常
//BKP->DR1用于保存是否第一次配置的设置
//返回1:正常
//其他:错误代码
u8 RTC_Init(void)
{
//检查是不是第一次配置时钟
u8 temp=0;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能PWR和BKP外设时钟
PWR_BackupAccessCmd(ENABLE); //使能后备寄存器访问
if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050) //从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎
{
BKP_DeInit(); //复位备份区域
//RCC_LSEConfig(RCC_LSE_ON); //设置外部低速晶振(LSE),使用外设低速晶振
RCC_LSICmd(ENABLE);//开启内部低速晶振LSI
//while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //检查指定的RCC标志位设置与否,等待外部低速晶振就绪
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) //检查指定的RCC标志位设置与否,等待内部低速晶振就绪
{
temp++;
delay_ms(10);
}
if(temp>=250)return 0;//初始化时钟失败,晶振有问题
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); //设置RTC时钟(RTCCLK),选择LSI作为RTC时钟
//RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟
RCC_RTCCLKCmd(ENABLE); //使能RTC时钟
RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成
RTC_WaitForSynchro(); //等待RTC寄存器同步
RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成
RTC_EnterConfigMode();/// 允许配置
RTC_SetPrescaler(32767); //设置RTC预分频的值
RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成
RTC_SetCounter(0); //初始值设定为0s
RTC_WaitForLastTask();
RTC_ExitConfigMode(); //退出配置模式
BKP_WriteBackupRegister(BKP_DR1, 0X5050); //向指定的后备寄存器中写入用户程序数据
}
else//系统继续计时
{
PWR_BackupAccessCmd(DISABLE);
RTC_WaitForSynchro(); //等待最近一次对RTC寄存器的写操作完成
RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成
}
RTC_NVIC_Config();//RCT中断分组设置
return 1; //ok
}
//RTC定时闹钟时间设置以及开启
void RTC_Set_Alarm_Time(uint32_t AlarmValue)
{
if(AlarmValue == 0)
{
return;
}
EXTI_ClearITPendingBit(EXTI_Line17);
RTC_ClearFlag(RTC_FLAG_ALR);
PWR_BackupAccessCmd(ENABLE);
RTC_EnterConfigMode();
RTC_SetAlarm(AlarmValue+RTC_GetCounter()); //闹钟值设定为AlarmValue秒
RTC_WaitForLastTask();
RTC_ExitConfigMode();
PWR_BackupAccessCmd(DISABLE);
RTC_NVIC_Config();
RTC_ITConfig(RTC_IT_ALR, ENABLE); //使能RTC闹钟中断
}
//RTC闹钟中断
void RTCAlarm_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line17);
RTC_ClearFlag(RTC_FLAG_ALR);
SystemInit();//重要,由于停机下对所有时钟关闭,所以唤醒需要重新配置时钟!!
if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)
{
PWR_ClearFlag(PWR_FLAG_WU);// 清除唤醒标志
}
RTC_ITConfig(RTC_IT_ALR, DISABLE); //失能RTC闹钟中断
}
//系统进入停机模式
void Sys_Enter_STOPMode(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能PWR外设时钟
PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);//进入停机模式
}
/***************************************************************************
名 称:MCU_STOP
功 能:MCU进入停机模式,且期间会唤醒进行喂狗,避免看门狗复位
入口参数:
uint32_t Stop_Time :停机时间长度(单位:秒);
uint32_t Wdg_Time :休眠期间唤醒喂狗间隔(单位:秒),要小于看门狗复位时间,否则会来不及喂狗导致MCU复位
出口参数:无
说 明:
调用方法:MCU_STOP(300,15);即MCU休眠300S,期间每隔15S喂狗一次
***************************************************************************/
void MCU_STOP(uint32_t Stop_Time,uint32_t Wdg_Time)
{
if((Stop_Time == 0) || (Wdg_Time == 0))//参数检测
{
return;
}
if(RTC_Init()) //RTC初始化成功
{
uint32_t i = 0;
uint32_t cycle_times = 0; //循环次数
uint32_t last_time = 0; //最后一次定时时间
cycle_times = Stop_Time/Wdg_Time; //取商
last_time = Stop_Time%Wdg_Time; //取余
for(i = 0;i < cycle_times;i++)
{
IWDG_Feed(); //看门狗喂狗
RTC_Set_Alarm_Time(Wdg_Time); //设置唤醒时间
Sys_Enter_STOPMode(); //系统进入停机模式
}
if(last_time != 0)
{
IWDG_Feed(); //看门狗喂狗
RTC_Set_Alarm_Time(last_time); //设置唤醒时间
Sys_Enter_STOPMode(); //系统进入停机模式
}
IWDG_Feed(); //看门狗喂狗
}
}
应用中直接使用MCU_STOP函数进入休眠即可。
整个工程文件下载:
关注公众号:逸趣汇
微信号:yiquhui666
发送:010301 或 RTC 获取下载链接。