打印
[其他ST产品]

arm中断保护和恢复_STM32低功耗待机模式+RTC闹钟中断唤醒

[复制链接]
楼主: 远芳侵古道
手机看帖
扫描二维码
随时随地手机跟帖
21
远芳侵古道|  楼主 | 2023-8-27 15:09 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
框图中浅灰色的部分都是属于备份域的,在VDD掉电时可在VBAT的驱动下继续运行。这部分仅包括RTC的分频器,计数器,和闹钟控制器。==若VDD电源有效,RTC可以触发RTC Second(秒中断)、RTCOverflow(溢出事件)和RTCAlarm(闹钟中断)==。从结构图可以分析到,其中的定时器溢出事件无法被配置为中断。若STM32原本处于待机状态,可由闹钟事件或WKUP事件(外部唤醒事件,属于EXTI模块,不属于RTC)使它退出待机模式。闹钟事件是在计数器RTCCNT的值等于闹钟寄存器RTCALR的值时触发的。

使用特权

评论回复
22
远芳侵古道|  楼主 | 2023-8-27 15:10 | 只看该作者

在备份域中所有寄存器都是16位的,RTC控制相关的寄存器也不例外。它的计数器RTCCNT的32位由RTCCNTL和RTCCNTH两个寄存器组成,分别保存定时计数值的低16位和高16位。在配置RTC模块的时钟时,通常把输入的32768Hz的RTCCLK进行32768分频得到实际驱动计数器的时钟TR CLK=RTCCLK/32768=1Hz,计时周期为1秒,计时器在TR_CLK的驱动下计数,即每秒计数器RTC_CNT的值加1。

使用特权

评论回复
23
远芳侵古道|  楼主 | 2023-8-27 15:10 | 只看该作者
六、程序讲解
为了能够更加清楚地了解利用RTC闹钟中断唤醒待机模式,假设现在利用STM3进行超声波测距,当距离大于1米时,单片机进入休眠状态,10秒钟后RTC自动唤醒STM32继续测量。在一米范围内不休眠,一但距离大于1米就开始休眠,10秒后唤醒继续测量。

使用特权

评论回复
24
远芳侵古道|  楼主 | 2023-8-27 15:10 | 只看该作者
rtc.c
#include "sys.h"
#include "delay.h"
#include "rtc.h"
//实时时钟配置
//初始化RTC时钟,同时检测时钟是否工作正常
void RTC_Init()
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP|RCC_APB1Periph_PWR,ENABLE);//使能PWR和BKP外设时钟   
//默认情况下,RTC 所属的备份域禁止访问,可使用库函数 PWR_BackupAccessCmd 使能访问
PWR_BackupAccessCmd(ENABLE);//允许访问备份区域,后备区域解锁   
if(PWR_GetFlagStatus(PWR_FLAG_SB)!=RESET) //如果现在处于待机模式
{
  PWR_ClearFlag(PWR_FLAG_SB);             //清除待机模式
  RTC_ITConfig(RTC_IT_SEC, ENABLE);     //打开RTC中断
  RTC_WaitForSynchro();                   //等待RTC寄存器同步  
}
else
{
  BKP_DeInit();//复位备份区域 使用此函数必须调用RCC_APB1PeriphClockCmd()函数
  RCC_LSEConfig(RCC_LSE_ON);//设置外部低速晶振(LSE),外部32.768KHZ晶振开启
  while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //等待稳定
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //设置RTC时钟(RTCCLK),选择LSE(晶振频率为 32.768KHz)作为RTC时钟   
  RCC_RTCCLKCmd(ENABLE);    //使能RTC时钟   
  RTC_WaitForLastTask();   //等待RTC寄存器同步,因为RTC时钟是低速的,内环时钟是高速的,所以要同步
  RTC_WaitForSynchro();     //写寄存器之前要确保上一次RTC的操作完成
  //下面这两条语句是开启RTC秒中断的函数,每过1秒钟产生一次中断,就进入了中断服务函数
  RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC秒中断
  RTC_WaitForLastTask();           //确保上一次 RTC 的操作完成  
  
  RTC_EnterConfigMode();    //进入RTC配置模式
  RTC_SetCounter(0);        //初始值设定为0s 在使用本函数前必须先调用函数RTC_WaitForLastTask();等待标志位RTOFF被设置
  RTC_WaitForLastTask();  
  
  RTC_SetPrescaler(32767);  //设置RTC分频: 使 RTC周期为1s  RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) = 1HZ 在使用本函数前必须先调用函数RTC_WaitForLastTask();等待标志位RTOFF被设置
  RTC_WaitForLastTask();    //确保上一次 RTC 的操作完成
  RTC_ExitConfigMode();     //退出RTC 配置模式
}
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;  
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
NVIC_Init(&NVIC_InitStructure);  

}
void RTC_IRQHandler()
{
    if(RTC_GetITStatus(RTC_IT_SEC)!=RESET)  //是否秒中断发生
{  
  printf("Time is  =%d rn",RTC_GetCounter()); //输出此时的秒数
}
RTC_WaitForLastTask();
RTC_ClearITPendingBit(RTC_IT_SEC|RTC_IT_OW); //清除秒中断标志位和溢出位
}

使用特权

评论回复
25
远芳侵古道|  楼主 | 2023-8-27 15:10 | 只看该作者
rtc.h
#ifndef __RTC_H
#define __RTC_H
#include "sys.h"

void RTC_Init(void);

#endif

使用特权

评论回复
26
远芳侵古道|  楼主 | 2023-8-27 15:10 | 只看该作者
main.c
int main(void)
{
  int Distance_data=0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //NVIC优先级分组2
delay_init();                                   //延时函数初始化
uart_init(115200);                              //串口1初始化 PA9-RX PA10-TX
LED_Init();                                  //LED端口初始化
Beep_Init();                              //BEEP端口初始化
OLED_Init() ;                                   //OLED端口初始化
RTC_Init();
while(1)
{
     Distance_data=Ultrasonic_Ranging();
  if(Distance_data>=1500)
  {
   printf("进入休眠!n");
   RTC_SetAlarm(RTC_GetCounter()+10); //闹钟在此时刻加上10秒
   RTC_WaitForLastTask();             //等待最近一次对RTC寄存器的写操作完成
   PWR_EnterSTANDBYMode();            //进入待机(STANDBY)模式   
  }
}
}

使用特权

评论回复
27
chenqianqian| | 2024-5-10 07:54 | 只看该作者
ST的低功耗模式设计还是很合理

使用特权

评论回复
28
Bowclad| | 2024-5-12 23:30 | 只看该作者
rtc是怎么触发中断的啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则