stm32—PWR power control (sleep mode\stop mode\standby mode)

Graphic and text overview:

!!!!!!!!!Attention!!!!!!!!!

Every time you use the __WFI() instruction or the __WFE() instruction to program and download, if you need to re-download other programs, you need to exit the sleep mode. The download operation at this time is: press and hold the reset button without letting go, click download program, and then let go to download the new program to the microcontroller.

Sleep mode:

Code:

#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Serial.h"

/*
In serial communication, first perform "Running" flashing, and then instruct the CPU to enter sleep mode through __WFI()
And wait for any interrupt to wake up, so when the serial port sends data, it will enter the interrupt function of the USART1 channel.
At this time, wake up the CPU and continue the while loop until it encounters the __WFI() instruction and continues to wait for the interrupt to wake up.
---Sleep mode can save power consumption---
*/

uint8_t RxData;

int main(void)
{
OLED_Init();
Serial_Init();

OLED_ShowString(1, 1, "RxData:");
\t
\t
while(1)
{
if(Serial_GetRxFlag() == 1)
{
RxData = Serial_GetRxData();
Serial_SendByte(RxData); //Transmit the data to the sending area and let the serial port assistant receive it
OLED_ShowHexNum(1, 8, RxData, 2);
}
\t\t
OLED_ShowString(2, 1, "Running");
Delay_ms(100);
OLED_ShowString(2, 1, " ");
Delay_ms(100);
\t\t
__WFI(); //CPU enters sleep mode and waits for interrupt to wake up
\t\t
}
}


Key code:

 __WFI(); //CPU enters sleep mode and waits for interrupt to wake up

The specific operations correspond to the following figure:

Stop mode:

Code:

#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"

/*
  The purpose of this experiment---to count through-beam infrared sensors in stop mode.
  By turning on the PWR peripheral clock + configuring the PWR_EnterSTOPMode function parameters,
  Let PWR enter stop mode. To exit stop mode, you need to wait for external interrupt to wake up.
  Therefore, when the times are not counted (that is, the external interrupt function is not entered), the chip is still in stop mode.
  When the through-beam infrared sensor senses the count (enters the external interrupt function at this time), it wakes up the chip
  Continue running the previously paused program and repeat.
*/


int main(void)
{
OLED_Init();
CountSensor_Init();
\t
//Turn on the peripheral clock of PWR
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
\t
\t
OLED_ShowString(1, 1, "CountSensor:");
\t

while(1)
{
OLED_ShowNum(2, 1, CountSensor_Get(), 5);
\t\t
OLED_ShowString(3, 1, "Running");
Delay_ms(100);
OLED_ShowString(3, 1, " ");
Delay_ms(100);
\t\t
/*
PWR enters stop mode
---1.Specify the regulator status in stop mode
---2. Specify whether to use the WFI or WFE instruction to enter stop mode.
*/
PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
/*
When an interrupt or wake-up event causes exit from stop mode, HSI is selected as the system clock (8MHz),
Therefore, it is necessary to reset the RCC clock configuration to the default reset state (i.e. HSE*9 = 72MHz)
*/
SystemInit();
}
}

Key code:

 //Enable PWR peripheral clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
 /*
PWR enters stop mode
---1.Specify the regulator status in stop mode
---2. Specify whether to use the WFI or WFE instruction to enter stop mode.
*/
PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);
/*
When an interrupt or wake-up event causes exit from stop mode, HSI is selected as the system clock (8MHz),
Therefore, it is necessary to reset the RCC clock configuration to the default reset state (i.e. HSE*9 = 72MHz)
*/
SystemInit(); 

The specific operations correspond to the following figure:

Standby mode:

Code:

#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "MyRTC.h"

/*
Standby mode (try to turn off all power-consuming circuits that can be turned off externally to reduce power consumption)
---The program needs to turn on the PWR peripheral clock and set the specified wake-up standby mode
Each time the PWR_EnterSTANDBYMode function is run, it enters standby mode.
The code program below the PWR_EnterSTANDBYMode function will not run.
And every time after waking up, the program will start running again, so in the main program you can
Remove the while loop

*/
int main(void)
{
OLED_Init();
MyRTC_Init();
\t
//Turn on the peripheral clock of PWR
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);
\t
OLED_ShowString(1, 1, "CNT:"); //Second counter value CNT
OLED_ShowString(2, 1, "ALR:"); //Alarm value Alarm
OLED_ShowString(3, 1, "ALRF:"); //Alarm clock flag
\t
/*
1. The first wake-up method---the rising edge of the WKUP pin (see which pin the WKUP pin is located in the chip pin diagram)
Enable the WAKEUP pin of the chip and wake up the standby mode when the WAKEUP pin rises
*/
PWR_WakeUpPinCmd(ENABLE);
\t
/*
2. The second wake-up method---the rising edge of RTC alarm event
Set the alarm clock to 10 seconds after the current time (when the value of CNT is the same as the value of Alarm, the RTC_FLAG_ALR alarm flag bit will be set to 1)
*/
uint32_t Alarm = RTC_GetCounter() + 10;
RTC_SetAlarm(Alarm);
\t
OLED_ShowNum(2, 6, Alarm, 10); //Display the value of Alarm
\t
while(1)
{
//Get the value of the counting register
OLED_ShowNum(1, 6, RTC_GetCounter(), 10);
//Get the alarm clock flag
OLED_ShowNum(3, 6, RTC_GetFlagStatus(RTC_FLAG_ALR), 1);
\t\t
//Display STANDBY, indicating that it is in standby mode
OLED_ShowString(4, 9, "STANDBY");
Delay_ms(1000);
OLED_ShowString(4, 9, " ");
Delay_ms(100);
\t\t
OLED_Clear();//Clear the OLED screen (analog module is powered off)
\t\t
PWR_EnterSTANDBYMode();//Enter standby mode
}
}

Key code:

 //Enable PWR peripheral clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);

/*
1. The first wake-up method---the rising edge of the WKUP pin (see which pin the WKUP pin is located in the chip pin diagram)
Enable the WAKEUP pin of the chip and wake up the standby mode when the WAKEUP pin rises
*/
PWR_WakeUpPinCmd(ENABLE);


/*
2. The second wake-up method---the rising edge of RTC alarm event
Set the alarm clock to 10 seconds after the current time (when the value of CNT is the same as the value of Alarm, the RTC_FLAG_ALR alarm flag bit will be set to 1)
*/
uint32_t Alarm = RTC_GetCounter() + 10;
RTC_SetAlarm(Alarm);


PWR_EnterSTANDBYMode();//Enter standby mode

The specific operations correspond to the following figure:

Supplement: Modify the main frequency

Code:

#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"

/*
Modify the main frequency (Delay_ms default is 72MHz)
At the default main frequency of 72MHz, the flashing period of the word "Running" on the OLED screen is 1s.
By modifying the writable attribute of the system_stm32f10x.c file, set the main frequency to 36MHz
At this time, the flashing period of the word "Running" on the OLED screen is 2s, that is, the frequency is delayed by 1 time.
*/

int main(void)
{
OLED_Init();
\t
OLED_ShowString(1, 1, "SYSCLK:");
OLED_ShowNum(1, 8, SystemCoreClock, 8); //Display the main frequency of the system clock
\t

\t
while(1)
{
OLED_ShowString(2, 1, "Running");
Delay_ms(500);
OLED_ShowString(2, 1, " ");
Delay_ms(500);
}
}

Modify the main frequency here under the system_stm32f10x.c file: