STM32深度睡眠唤醒方式

#define DEF_BASE_YEAR 2013
#define DEF_YEAR_MAX 99
#define DEF_YEAR_MIN 0

#pragma pack(1)
typedef struct{
uint16 Year;
uint8 Month;
uint8 Day;
uint8 Hour;
uint8 Min;
uint8 Sec;
uint8 Week;
}TIMESTR;

#pragma pack()



#define RTC_CLOCK_SOURCE_LSI
//#define RTC_CLOCK_SOURCE_LSE
#define FIRST_DATA          0x32F2


__IO uint32_t AsynchPrediv = 0, SynchPrediv = 0;
RTC_InitTypeDef   RTC_InitStructure;
RTC_TimeTypeDef   RTC_TimeStructure;
RTC_DateTypeDef   RTC_DateStructure;


void RTC_Config(void);
void RTC_AlarmConfig(void);
void RTC_WutConfig(void);
void RTC_PwConfig(void);


 void MCU_RtcInit( void )
{
TIMESTR str_time;
uint8 TimeSetFlg=0;


/* Enable the PWR APB1 Clock Interface */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);


/* Allow access to BKP Domain */
PWR_BackupAccessCmd(ENABLE);

if (RTC_ReadBackupRegister(RTC_BKP_DR0)!=FIRST_DATA)
{
/* RTC Configuration */
RTC_Config();
/* Write to the first RTC Backup Data Register */
  RTC_WriteBackupRegister(RTC_BKP_DR0, FIRST_DATA);
}
else
{
TimeSetFlg = 1;
str_time = MCU_GetCurTime();
RTC_PwConfig(); 
}
RTC_AlarmConfig();
if (TimeSetFlg)
{
MCU_CurTimeSet(str_time);
} 

RTC_WutConfig();
  }


/**
  * @brief  Configure the RTC peripheral by selecting the clock source.
  * @param  None
  * @retval None
  */
  
void RTC_Config(void)
{
 /* Enable the PWR clock */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);


  /* Allow access to RTC */
  PWR_BackupAccessCmd(ENABLE);


  /* Reset RTC Domain */
  RCC_BackupResetCmd(ENABLE);
  RCC_BackupResetCmd(DISABLE);
    
#if defined (RTC_CLOCK_SOURCE_LSI)  /* LSI used as RTC source clock*/
/* The RTC Clock may varies due to LSI frequency dispersion. */
  /* Enable the LSI OSC */ 
  RCC_LSICmd(ENABLE);


  /* Wait till LSI is ready */  
  while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
  {
  }


  /* Select the RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
  
  SynchPrediv = 0xFF;
  AsynchPrediv = 0x7F;


#elif defined (RTC_CLOCK_SOURCE_LSE) /* LSE used as RTC source clock */
  /* Enable the LSE OSC */
  RCC_LSEConfig(RCC_LSE_ON);


  /* Wait till LSE is ready */  
  while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
  {
  }


  /* Select the RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
  
  SynchPrediv = 0xFF;
  AsynchPrediv = 0x7F;


#else
  #error Please select the RTC Clock source inside the main.c file
#endif /* RTC_CLOCK_SOURCE_LSI */


  /* Calendar Configuration */
  RTC_InitStructure.RTC_AsynchPrediv = AsynchPrediv;
  RTC_InitStructure.RTC_SynchPrediv =  SynchPrediv;
  RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
  RTC_Init(&RTC_InitStructure);
  
  /* Set Current Time and Date */
  //RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure);  
  //RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure); 


  /* Enable the Backup SRAM low power Regulator to retain it's content in VBAT mode */
  PWR_BackupRegulatorCmd(ENABLE);


  /* Wait until the Backup SRAM low power Regulator is ready */
  while(PWR_GetFlagStatus(PWR_FLAG_BRR) == RESET)
  {
  }
}


void RTC_PwConfig(void)
{



/* Reset RTC Domain */
RCC_BackupResetCmd(ENABLE);
RCC_BackupResetCmd(DISABLE);
RTC_WriteBackupRegister(RTC_BKP_DR0, FIRST_DATA);


#if defined (RTC_CLOCK_SOURCE_LSI)  /* LSI used as RTC source clock*/
/* The RTC Clock may varies due to LSI frequency dispersion. */
/* Enable the LSI OSC */ 
RCC_LSICmd(ENABLE);


/* Wait till LSI is ready */  
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{
}


/* Select the RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);


SynchPrediv = 0xFF;
AsynchPrediv = 0x7F;


#elif defined (RTC_CLOCK_SOURCE_LSE) /* LSE used as RTC source clock */
/* Enable the LSE OSC */
RCC_LSEConfig(RCC_LSE_ON);


/* Wait till LSE is ready */  
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{
}


/* Select the RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);


SynchPrediv = 0xFF;
AsynchPrediv = 0x7F;

#else
#error Please select the RTC Clock source inside the main.c file
#endif /* RTC_CLOCK_SOURCE_LSI */
}


void RTC_AlarmConfig(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
RTC_AlarmTypeDef RTC_AlarmStructure;
NVIC_InitTypeDef NVIC_InitStructure;

/* EXTI configuration */
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);


/* Enable the RTC Alarm Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

/* Set the alarmA Masks */
//RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_All&(~RTC_AlarmMask_Seconds);
RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_All;
  RTC_SetAlarm(RTC_Format_BCD, RTC_Alarm_A, &RTC_AlarmStructure);


/* Set AlarmA subseconds and enable SubSec Alarm : generate 8 interripts per Second */
  RTC_AlarmSubSecondConfig(RTC_Alarm_A, 0xff, RTC_AlarmSubSecondMask_SS14_8);


/* Enable AlarmA interrupt */
RTC_ITConfig(RTC_IT_ALRA, ENABLE);


/* Enable the RTC Clock */
RCC_RTCCLKCmd(ENABLE);


/* Wait for RTC APB registers synchronisation */
RTC_WaitForSynchro();


/* Enable the alarmA */
RTC_AlarmCmd(RTC_Alarm_A, ENABLE);


}


void RTC_WutConfig(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

/* Enable the RTC Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);


/* EXTI configuration *******************************************************/
EXTI_ClearITPendingBit(EXTI_Line22);
EXTI_InitStructure.EXTI_Line = EXTI_Line22;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);

/* Configure the RTC Wakeup Clock source and Counter (Wakeup event each 1 second) */
RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div16);
RTC_SetWakeUpCounter(859);


/* Enable the Wakeup Interrupt */
RTC_ITConfig(RTC_IT_WUT, ENABLE);


/* Enable Wakeup Counter */
RTC_WakeUpCmd(ENABLE); 


}


void RTC_Alarm_IRQHandler(void)
{
  /* Check on the AlarmA falg and on the number of interrupts per Second (60*8) */
  if(RTC_GetITStatus(RTC_IT_ALRA) != RESET) 
  { 
/* Clear RTC AlarmA Flags */
RTC_ClearITPendingBit(RTC_IT_ALRA);
  EXTI_ClearITPendingBit(EXTI_Line17);  
//ExitStopMode();
  }
  /* Clear the EXTIL line 17 */
}


void RTC_WKUP_IRQHandler(void)
{
uint8 err;

  if(RTC_GetITStatus(RTC_IT_WUT) != RESET)
  {    
RTC_ClearITPendingBit(RTC_IT_WUT);
EXTI_ClearITPendingBit(EXTI_Line22);
  ExitStopMode();
  }
}


TIMESTR MCU_GetCurTime(void)
{ 
TIMESTR timer;


/* Get the current Time */
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
/* Get the current Date */
RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure);


//timer.Year=RTC_DateStructure.RTC_Year;//得到年份
if (RTC_DateStructure.RTC_Year>DEF_YEAR_MAX)
{
timer.Year = DEF_BASE_YEAR;
}
else
{
timer.Year = RTC_DateStructure.RTC_Year + DEF_BASE_YEAR;
}
timer.Month=RTC_DateStructure.RTC_Month;//得到月份
timer.Day=RTC_DateStructure.RTC_Date;  //得到日期 
timer.Hour=RTC_TimeStructure.RTC_Hours;     //小时
timer.Min=RTC_TimeStructure.RTC_Minutes; //分钟 
timer.Sec=RTC_TimeStructure.RTC_Seconds; //秒钟
timer.Week=RTC_DateStructure.RTC_WeekDay;//获取星期   

return timer;
}


BOOL  MCU_CurTimeSet(TIMESTR Timer)
{
/* Set the Time */
RTC_TimeStructure.RTC_Hours   = Timer.Hour;
RTC_TimeStructure.RTC_Minutes = Timer.Min;
RTC_TimeStructure.RTC_Seconds = Timer.Sec;


/* Set the Date */
if (Timer.Year<DEF_BASE_YEAR||Timer.Year>DEF_BASE_YEAR+DEF_YEAR_MAX)
{
RTC_DateStructure.RTC_Year = DEF_YEAR_MIN;
}
else
{
RTC_DateStructure.RTC_Year = Timer.Year-DEF_BASE_YEAR;
}
RTC_DateStructure.RTC_Month = Timer.Month;
RTC_DateStructure.RTC_Date = Timer.Day;  
//RTC_DateStructure.RTC_Year = Timer.Year; 
RTC_DateStructure.RTC_WeekDay = Timer.Week; 


/* Set Current Time and Date */
RTC_SetTime(RTC_Format_BIN, &RTC_TimeStructure);  
RTC_SetDate(RTC_Format_BIN, &RTC_DateStructure); 
return TRUE;    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: STM32的Stop模式是一种低功耗模式,可以降低芯片的功耗以延长电池寿命。在Stop模式下,芯片的大部分功能都被关闭,只有一些必要的模块继续工作。 在使用HAL库实现Stop模式的唤醒时,可以按照以下步骤进行: 1. 配置待唤醒的外设:使用HAL库提供的相应函数对需要唤醒的外设进行配置,如GPIO、外部中断等。确保外设能够唤醒芯片。 2. 配置唤醒源:使用HAL库提供的函数对Stop模式的唤醒源进行配置。常见的唤醒源包括外部中断、RTC闹钟、唤醒定时器等。根据实际需求选择相应的唤醒源,并配置相应的参数。 3. 进入Stop模式:调用HAL库提供的函数将芯片进入Stop模式。可以选择进入低功耗或深度睡眠模式。 4. 唤醒处理:当外部事件触发唤醒源后,芯片将会被唤醒并执行唤醒后的处理。可以使用中断的方式处理唤醒事件,或者在主循环中轮询检测唤醒事件。 5. 恢复外设和时钟:在芯片被唤醒后,需要重新配置和使能之前被关闭的外设和时钟。使用HAL库提供的相应函数对外设和时钟进行恢复。 需要注意的是,在Stop模式下芯片的工作频率会降低,因此需要重新校准外部设备(如外部晶振)的时钟。 通过以上步骤,就可以使用HAL库实现STM32的Stop模式唤醒。在低功耗要求较高的应用中,采用Stop模式进行合理的功耗管理可以达到较高的电池寿命。 ### 回答2: STM32的Stop模式是一种功耗较低的模式,在这种模式下,系统会停止运行,只保留必要的模块以维持一些基本功能。当需要唤醒系统时,HAL库提供了一种方便的方法。 首先,我们需要在使用Stop模式前进行一些初始化设置。我们可以调用HAL_PWR_EnterSTOPMode函数,将系统设置为Stop模式。在进入Stop模式前,我们需要关闭不需要的外设以降低功耗,例如关闭闹钟、定时器、串口等。同时,我们还需要配置唤醒源,以决定何时唤醒系统。 在停止模式下,系统处于低功耗状态,只有唤醒源被触发时,才能唤醒系统。当唤醒源被触发时,系统会从Stop模式中恢复。在STM32中,常见的唤醒源有外部中断、定时器中断、RTC闹钟中断等。我们可以使用HAL库提供的相应函数来配置唤醒源,例如HAL_PWR_EnableWakeUpPin函数用于配置外部中断唤醒。 当唤醒源被触发后,我们需要进行一些必要的操作以恢复系统。例如重新初始化各个外设,开启必要的中断以实现相应功能。然后,我们可以调用HAL_PWR_DisableWakeUpPin函数来关闭唤醒源,并将系统从Stop模式恢复到正常运行模式。 通过调用HAL库提供的相关函数,我们可以很方便地实现STM32的Stop模式唤醒功能。这种低功耗模式在一些对功耗有严格要求的应用中非常有用,能够有效地延长系统的电池寿命。 ### 回答3: STM32的Stop模式是一种低功耗模式,可以使MCU进入待机状态以减少能耗。HAL库是STM32的一个开发库,使用它可以简化MCU的编程过程。 在使用HAL库实现STM32的Stop模式唤醒时,需要以下几个步骤: 1. 配置RCC时钟:首先需要配置RCC (Reset and Clock Control)模块来启用所需的外设时钟。具体配置内容包括使能所需外设时钟,设置系统时钟源等。 2. 配置唤醒源:在进入Stop模式前,需要配置唤醒源以确定如何唤醒MCU。唤醒源可以是外部中断、定时器中断、低功耗定时器中断等。可以使用HAL库提供的相应函数进行配置。 3. 进入Stop模式:调用相应的HAL库函数进入Stop模式。在进入Stop模式前,需要进行一些准备工作,如关闭不需要的外设、保存必要的数据和状态等。然后调用HAL库提供的函数,将MCU设置为Stop模式。 4. 唤醒处理:当满足唤醒条件时,MCU会从Stop模式中唤醒唤醒后,需要进行一些处理,如重新使能外设时钟、恢复保存的数据和状态等。可以使用HAL库提供的相应函数完成这些处理。 需要注意的是,在使用HAL库实现Stop模式唤醒时,需要对不同型号的STM32芯片进行不同的配置和操作。具体的配置和操作方法可以参考相关的官方文档和参考资料。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

缥缈孤鸿_jason

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值