STM32CubeMX(stm32L151C8T6) 之RTC闹钟唤醒停机模式

  • Post author:
  • Post category:其他




基本知识介绍

1、37kHz低速内部RC,可以用于驱动独立看门狗和通过程序选择驱动RTC。 RTC用于从停机/

待机模式下自动唤醒系统

2、LSI时钟

LSI RC担当一个低功耗时钟源的角色,它可以在停机和待机模式下保持运行,为独立看门狗和

自动唤醒单元提供时钟。 LSI时钟频率大约40kHz(在30kHz和60kHz之间)。

3、LSI RC可以通过控制/状态寄存器(RCC_CSR)里的LSION位来启动或关闭。

4、注意: 只有大容量和互联型产品可以进行LSI校准



低功耗模式

在系统或电源复位以后,微控制器处于运行状态。当CPU不需继续运行时,可以利用多种低功
耗模式来节省功耗,例如等待某个外部事件时。用户需要根据最低电源消耗、最快速启动时间
和可用的唤醒源等条件,选定一个最佳的低功耗模式。



STM32F10xxx有三种低功耗模式:

● 睡眠模式(Cortex™-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时

钟(SysTick)等仍在运行)

● 停止模式(所有的时钟都已停止)

● 待机模式(1.8V电源关闭)

在这里插入图片描述



停止模式

	停止模式是在Cortex™-M3的深睡眠模式基础上结合了外设的时钟控制机制,在停止模式下电压
	调节器可运行在正常或低功耗模式。此时在1.8V供电区域的的所有时钟都被停止, PLL、 HSI和
	HSE RC振荡器的功能被禁止, SRAM和寄存器内容被保留下来。
	在停止模式下,所有的I/O引脚都保持它们在运行模式时的状态



进入停止模式

关于如何进入停止模式。

在停止模式下,通过设置电源控制寄存器(PWR_CR)的LPDS位使内部调节器进入低功耗模式,

能够降低更多的功耗。

如果正在进行闪存编程,直到对内存访问完成,系统才进入停止模式。

如果正在进行对APB的访问,直到对APB访问完成,系统才进入停止模式。

电源控制(PWR)

● 独立看门狗(IWDG):可通过写入看门狗的键寄存器或硬件选择来启动IWDG。一旦启动了

独立看门狗,除了系统复位,它不能再被停止。详见17.3节。

● 实时时钟(RTC):通过备份域控制寄存器 (RCC_BDCR)的RTCEN位来设置。

● 内部RC振荡器(LSI RC):通过控制/状态寄存器 (RCC_CSR)的LSION位来设置。

● 外部32.768kHz振荡器(LSE):通过备份域控制寄存器 (RCC_BDCR)的LSEON位设置。

在停止模式下,如果在进入该模式前ADC和DAC没有被关闭,那么这些外设仍然消耗电流。通

过设置寄存器ADC_CR2的ADON位和寄存器DAC_CR的ENx位为0可关闭这2个外设。

在这里插入图片描述

进入STOP模式,好像是手动进入的,RTC只是唤醒



待机模式

待机模式可实现系统的最低功耗。该模式是在Cortex-M3深睡眠模式时关闭电压调节器。整个

1.8V供电区域被断电。 PLL、 HSI和HSE振荡器也被断电。 SRAM和寄存器内容丢失。只有备份

的寄存器和待机电路维持供电。

可以通过设置独立的控制位,选择以下待机模式的功能:

● 独立看门狗(IWDG):可通过写入看门狗的键寄存器或硬件选择来启动IWDG。一旦启动了

独立看门狗,除了系统复位,它不能再被停止。详见17.3节。

● 实时时钟(RTC):通过备用区域控制寄存器(RCC_BDCR)的RTCEN位来设置。

● 内部RC振荡器(LSI RC):通过控制/状态寄存器(RCC_CSR)的LSION位来设置。

● 外部32.768kHz振荡器(LSE):通过备用区域控制寄存器(RCC_BDCR)的LSEON位设置。

退出待机模式

当一个外部复位(NRST引脚)、 IWDG复位、 WKUP引脚上的上升沿或RTC闹钟事件的上升沿发

生时(见图154: 简化的RTC框图),微控制器从待机模式退出。从待机唤醒后,除了电源控制/状

态寄存器(PWR_CSR)(见第4.4.2节),所有寄存器被复位。

从待机模式唤醒后的代码执行等同于复位后的执行(采样启动模式引脚、读取复位向量等)。 电源

控制/状态寄存器(PWR_CSR)(见第4.4.2节)将会指示内核由待机状态退出

在这里插入图片描述



低功耗模式下的自动唤醒(AWU)

RTC可以在不需要依赖外部中断的情况下唤醒低功耗模式下的微控制器(自动唤醒模式)。 RTC提

供一个可编程的时间基数,用于周期性从停止或待机模式下唤醒。通过对备份区域控制寄存器

(RCC_BDCR)的RTCSEL[1:0]位的编程,三个RTC时钟源中的二个时钟源可以选作实现此功

能。

● 低功耗32.768kHz外部晶振(LSE)

该时钟源提供了一个低功耗且精确的时间基准。 (在典型情形下消耗小于1µA)

● 低功耗内部RC振荡器(LSI RC)

使用该时钟源,节省了一个32.768kHz晶振的成本。但是RC振荡器将少许增加电源消耗。

为了用RTC闹钟事件将系统从停止模式下唤醒,必须进行如下操作:

● 配置外部中断线17为上升沿触发。

● 配置RTC使其可产生RTC闹钟事件。(其实就是闹钟事件)

如果要从待机模式中唤醒,不必配置外部中断线17。(但是好像用的就是中断线17)

开始深入学习

在这里插入图片描述

这里我们选用LSI,这个项目没有加外部低速时钟,

这里我还要使能中断

选择1HZ就是1s 如果你要5s唤醒一次只需要在wake up counter 填入 (5-1)

在这里插入图片描述

进入睡眠模式

WFI(等待中断) WFE (是等待事件)

接下来,我们看代码

先看看生成的rtc初始化代码,,这里面不用动都可以

/**
  ******************************************************************************
  * File Name          : RTC.c
  * Description        : This file provides code for the configuration
  *                      of the RTC instances.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "rtc.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

RTC_HandleTypeDef hrtc;

/* RTC init function */
void MX_RTC_Init(void)
{
  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef sDate = {0};

  /** Initialize RTC Only 
  */
  hrtc.Instance = RTC;
  hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
  hrtc.Init.AsynchPrediv = 127;
  hrtc.Init.SynchPrediv = 255;
  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN Check_RTC_BKUP */
    
  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date 
  */
  sTime.Hours = 0x8;
  sTime.Minutes = 0x0;
  sTime.Seconds = 0x0;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  sDate.Month = RTC_MONTH_JANUARY;
  sDate.Date = 0x8;
  sDate.Year = 0x18;

  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
	//HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2);
  /** Enable the WakeUp 
  */
  //修改这里就可以修改唤醒时间
  if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 4, RTC_WAKEUPCLOCK_CK_SPRE_16BITS) != HAL_OK)
  {
    Error_Handler();
  }
		
}

void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
{

  if(rtcHandle->Instance==RTC)
  {
  /* USER CODE BEGIN RTC_MspInit 0 */

  /* USER CODE END RTC_MspInit 0 */
    /* RTC clock enable */
    __HAL_RCC_RTC_ENABLE();

    /* RTC interrupt Init */
    HAL_NVIC_SetPriority(RTC_WKUP_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);
  /* USER CODE BEGIN RTC_MspInit 1 */

  /* USER CODE END RTC_MspInit 1 */
  }
}

void HAL_RTC_MspDeInit(RTC_HandleTypeDef* rtcHandle)
{

  if(rtcHandle->Instance==RTC)
  {
  /* USER CODE BEGIN RTC_MspDeInit 0 */

  /* USER CODE END RTC_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_RTC_DISABLE();

    /* RTC interrupt Deinit */
    HAL_NVIC_DisableIRQ(RTC_WKUP_IRQn);
  /* USER CODE BEGIN RTC_MspDeInit 1 */

  /* USER CODE END RTC_MspDeInit 1 */
  }
} 

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

接下来就是进入停止模式

进入之前需要把所有的io口设置成模拟输入,不然即使你进了停止模式,电流还是有300ua

	
	GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0 
                          |GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4 
                          |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8 
                          |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
	
	 GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
	
	GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 
                          |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 
                          |GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 
                          |GPIO_PIN_12|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_2|GPIO_PIN_1|GPIO_PIN_10 
                          |GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14 |GPIO_PIN_11
                          |GPIO_PIN_15|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5 
                          |GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
	
  HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_STOPENTRY_WFI);  //直接进入停止模式,中断唤醒。然后时间到了就会唤醒


唤醒stop模式后,需要重新配置时钟,因为停止模式会关掉除低频时钟外的其他时钟,比如MSI、HSI、 HSE、 PPL这些,都会关闭。停止模式唤醒后,默认是用MSI时钟,假如你用的不是MSI,就要重新配置时钟。停止模式,就是让CPU停在那里,唤醒后,继续执行,所以配置时钟要放在停止模式函数的后面。这样就行了

SystemClock_Config();

因为上面我们把所有io的模式设置成了模拟输入,所以我们还得初始化io

//把使用到的外设io在初始化一遍

HAL_UART_MspInit(&huart1);
HAL_ADC_MspInit(&hadc);
HAL_SPI_MspInit(&hspi2);
MX_GPIO_Init();

就上面的所有设置我做到了 7ua 供大家参考

这里我还使用了nrf24l01

也把nrf24l04低功耗了,,,功耗也才7.9ua

//让他进入低功耗模式

HAL_GPIO_WritePin(NRF2401_CE_GPIOX,NRF2401_CE_PIN,0);
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x02); 

但是光上面的两行代码,还不够,功耗还是有350ua 带pa的

还需要设置io口

GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15|GPIO_PIN_14|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

多次尝试发现这么设置,才能把功耗降下去

这里STM32L151的软件我已经全部告知,不用谢



版权声明:本文为qq_41531368原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。