CKS32F4xx系列低功耗模式之STANDBY模式

描述

CKS32F4xx低功耗模式

STANDBY模式

第十七期 2023.7.6

    本章中,我们主要对CKS32F4xx系列的待机模式(STANDBY)做详细介绍。在该模式下,芯片功耗最低,1.2V供电区域、PLL、HSI和HSE振荡器也完全被关闭。除备份域(RTC寄存器、RTC备份寄存器和备份SRAM)和待机电路中的寄存器外,SRAM和寄存器内容丢失。因此,从待机模式唤醒后,只能从头开始执行程序,那我们如何进入STANDBY模式及唤醒方式,可以按照下述表格中的步骤执行即可:

寄存器

CKS32F4xx系列标准库把进入STANDBY模式这部分的操作封装到PWR_EnterSTANDBYMode函数中了,需要先通过PWR_CR设置PDDS位以及SLEEPDEEP位,使得芯片进入深度睡眠时进入待机模式,接着调用__force_stores函数确保存储操作完毕后再调用WFI指令,从而进入待机模式。需要注意的是,调用本函数前,还需要清空WUF 寄存器位才能进入待机模式。

RTC时钟简介

 

CKS32F4xx系列的RTC,是一个独立的BCD定时器/计数器,RTC提供一个日历时钟(包含年月日时分秒信息)、两个可编程闹钟(ALARM A和ALARM B)中断,以及一个具有中断功能的周期性可编程唤醒标志。RTC还包含用于管理低功耗模式的自动唤醒单元。两个32位寄存器包含二进码十进数格式(BCD)的秒、分钟、小时(12或24小时制)、星期几、日期、月份和年份。此外,还可提供二进制格式的亚秒值。系统可以自动将月份的天数补偿为28、29(闰年)、30和31天。并且还可以进行夏令时补偿。其它32位寄存器还包含可编程的闹钟亚秒、秒、分钟、小时、星期几和日期。此外,还可以使用数字校准功能对晶振精度的偏差进行补偿。RTC模块和时钟配置是在后备区域,即在系统复位或从待机模式唤醒后RTC的设置和时间维持不变,只要后备区域供电正常,那么RTC将可以一直运行。但是在系统复位后,会自动禁止访问后备寄存器和RTC,以防止对后备区域(BKP)的意外写操作。所以在要设置时间之前,先要取消备份区域(BKP)写保护。RTC的框图,如下图所示:

寄存器

 

采用RTC周期性唤醒STANDBY模式实验

程序设计主要要点如下:

① RTC初始化;

② RTC周期性自动唤醒;

③ 清除WUF标志位,进入待机状态。

1)初始化RTC配置函数

 

void CKS_RTC_Init(void)
{
  uint16_t retry = 0x1FFF; 
  RTC_InitTypeDef  RTC_InitStructure;


  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); 
  PWR_BackupAccessCmd(ENABLE); 


  RCC_LSEConfig(RCC_LSE_ON);   
  while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)  
  {
    retry--; 
    Delay(0xffff);
  }
  if(retry == 0)
  {
    return 1; 
  }
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);     
  RCC_RTCCLKCmd(ENABLE);   


  RTC_InitStructure.RTC_AsynchPrediv  =  0x7F;
  RTC_InitStructure.RTC_SynchPrediv   =  0xFF;
  RTC_InitStructure.RTC_HourFormat   =  RTC_HourFormat_24;
  RTC_Init(&RTC_InitStructure);
}

 

在CKS_RTC_Init函数中,用来初始化RTC配置以及日期和时钟,但只在首次设置时间,随后重新上电/复位都不再进行时间设置(前提是备份电池有电)。为了时间更为精准,这里选用了LSE,即外部32.768kHz晶振作为RTC_CLK的时钟源,而RTC时钟核心,要求提供1Hz的时钟,所以接着是设置RTC_CLK的预分频系数,包括异步和同步两个,这里设置异步分频因子为ASYNCHPREDIV为(127),同步分频因子为ASYNCHPREDIV(255),则产生的时钟CK_SPRE=32.768/(127+1)*(255+1)=1HZ,即每秒更新一次。

2)RTC周期性唤醒配置函数

 

void RTC_Set_WakeUp(uint32_t wksel, uint16_t cnt)
{ 
  NVIC_InitTypeDef   NVIC_InitStructure;
  EXTI_InitTypeDef   EXTI_InitStructure;


  RTC_WakeUpCmd(DISABLE);
  RTC_WakeUpClockConfig(wksel); 
  RTC_SetWakeUpCounter(cnt-1); 


  RTC_ClearITPendingBit(RTC_IT_WUT); 
  EXTI_ClearITPendingBit(EXTI_Line22); 
   
  RTC_ITConfig(RTC_IT_WUT, ENABLE); 
  RTC_WakeUpCmd(ENABLE); 


  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); 


  NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn; 
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
  NVIC_Init(&NVIC_InitStructure); 
}

 

在RTC_Set_WakeUp函数中,首先通过RTC_WakeUpCmd函数,关闭WakeUp,接着调用RTC_WakeUpClockConfig函数,配置WakeUp时钟分频系数及来源,然后通过调用RTC_SetWakeUpCounter,设置WakeUp自动装载寄存器,随后使能WakeUp,最后开启配置闹钟中断以及NVIC中断优先级。鉴于此处为RTC唤醒待机实验,仅做demo例程使用,因而不用编写中断服务函数。

3)芯片进入STANDBY模式

查阅CKS32F4xx系列标准库及相关手册,我们了解到使能RTC周期性唤醒,在进入STANDBY模式前,需要进行以下操作,代码如下:

 

void CKS_Set_Standby_Mode(void)
{    
  RTC_ITConfig(RTC_IT_TS|RTC_IT_WUT|RTC_IT_ALRB|RTC_IT_ALRA, DISABLE); 
  RTC_ClearITPendingBit(RTC_IT_TS|RTC_IT_WUT|RTC_IT_ALRB|RTC_IT_ALRA); 
  PWR_ClearFlag(PWR_FLAG_WU); 
    
  RTC_Set_WakeUp(RTC_WakeUpClock_CK_SPRE_16bits, 3);
    
  PWR_EnterSTANDBYMode();         
}

 

在CKS_Set_Standby_Mode函数中,先禁止RTC中断(ALRAIE、ALRBIE、TSIE、WUTIE和TAMPIE等),接着清零对应中断标志位,以及清除PWR唤醒(WUF)标志,然后调用RTC_Set_WakeUp函数,设置每3s后唤醒STANDBY模式,同时该函数中也重新使能RTC对应中断,最后调用PWR_EnterSTANDBYMode进入STANDBY模式。

4)主函数配置

本例程中主函数主要对上文所述函数调用,程序编译下载至开发板,先进行相关外设初始化后,直接进入STANDBY模式,每隔3s由RTC唤醒,随即又进入STANDBY模式,循环往复,主函数代码如下:

 

int main(void)
{  
  CKS_RTC_Init();       
  
  while (1)
  {        
    CKS_Set_Standby_Mode();    
  }
}

 

审核编辑:汤梓红

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分