PY32F003F18之sleep模式

一、WFI和WFE
WFI: wait for interrupt,是"等待中断"的意思;
WFE: wait for event,是"等待事件"的意思;

1)执行HAL_PWR_DisableSleepOnExit(),则令SLEEPONEXIT位置0;
当SLEEPDEEP=0,SLEEPONEXIT=0,如果执行WFI,则立即进入"sleep模式",中断唤醒后,程序会继续执行main()中的其它语句
退出睡眠方式是:中断


当SLEEPDEEP=0,SLEEPONEXIT=0,如果执行WFE,则立即进入"sleep模式",唤醒后,程序会继续执行main()中的其它语句;
退出睡眠方式是:唤醒事件,包括中断


2)执行HAL_PWR_EnableSleepOnExit(),则令SLEEPONEXIT位置1
若执行WFI或WFE,则立即进入"sleep模式";中断唤醒后,程序只执行"相应的中断服务程序",退出中断后,会再次进入"sleep模式",
因此,不再执行执行main()中的其它语句;
唤醒退出方式是:中断

3)执行HAL_PWR_EnableSEVOnPend(),则令SEVONPEND位置1;允许事件唤醒内核(包括中断唤醒),
在执行WFE指令前,需要先设置SEVONPEND=1,才可以使用事件唤醒,否则,只能使用中断唤醒;
但通过WFI进入的"sleep模式",即使设置SEVONPEND=1,事件也无法唤醒CPU核,不清楚原因?

翻译的文档,写得实在糟糕,一些功能性表格,就不截图了,免得会产生误解!!!

4)"stop模式"可以执行事件唤醒和中断唤醒。

注意:在sleep模式中,所有的"IO引脚"和"run模式"保持相同的电平状态;
在进入睡眠前,需要配置好"相应的唤醒源",关闭不用的模块,如SysTick,以便CPU进入Sleep模式;

二、测试程序

#include "SleepMode.h"

/*
"sleep模式"
WFI: wait for interrupt,是"等待中断"的意思;
WFE: wait for event,是"等待事件"的意思;

1)执行HAL_PWR_DisableSleepOnExit(),则令SLEEPONEXIT位置0;
当SLEEPDEEP=0,SLEEPONEXIT=0,如果执行WFI,则立即进入"sleep模式",中断唤醒后,程序会继续执行main()中的其它语句;
退出睡眠方式是:中断;
当SLEEPDEEP=0,SLEEPONEXIT=0,如果执行WFE,则立即进入"sleep模式",唤醒后,程序会继续执行main()中的其它语句;
退出睡眠方式是:唤醒事件,包括中断;


2)执行HAL_PWR_EnableSleepOnExit(),则令SLEEPONEXIT位置1;
若执行WFI或WFE,则立即进入"sleep模式";中断唤醒后,程序只执行"相应的中断服务程序",退出中断后,会再次进入"sleep模式",
因此,不再执行执行main()中的其它语句;
唤醒退出方式是:中断;

3)执行HAL_PWR_EnableSEVOnPend(),则令SEVONPEND位置1;允许事件唤醒内核(包括中断唤醒),
在执行WFE指令前,需要先设置SEVONPEND=1,才可以使用事件唤醒,否则,只能使用中断唤醒,
但通过WFI进入的"sleep模式",即使设置SEVONPEND=1,事件也无法唤醒CPU核,不清楚原因?

4)"stop模式"可以执行事件唤醒和中断唤醒。

注意:在sleep模式中,所有的"IO引脚"和"run模式"保持相同的电平状态;
在进入睡眠前,需要配置好"相应的唤醒源",关闭不用的模块,如SysTick,以便CPU进入Sleep模式;
*/

void EnterSLEEPMode_With_WFE(void);
void EnterSLEEPMode_With_WFI(void);
void EnterSLEEPMode_With_WFE_And_After_Interrupt(void);
void EnterSLEEPMode_With_WFI_And_After_Interrupt(void);

//函数功能:中断或事件唤醒后,程序会继续执行main()中的其它语句
//通过WFE进入的"sleep模式",退出方式是:唤醒事件,也可以是中断
void EnterSLEEPMode_With_WFE(void)
{
	__HAL_RCC_PWR_CLK_ENABLE();
	//PWR时钟使能
	//这一句不能少,否则,不能进入"sleep模式"
	HAL_PWR_DisableSleepOnExit();
	//则令SLEEPONEXIT位置0;
	//如果执行WFE,则立即进入"sleep模式"
	HAL_PWR_EnableSEVOnPend();
	//当"SEVONPEND=1"时,允许事件唤醒内核(包括中断唤醒)
	//这一句不能少,否则,事件无法唤醒CPU
  HAL_PWR_EnterSLEEPMode(PWR_SLEEPENTRY_WFE);
	//令SLEEPDEEP=0,然后执行WFE,令CPU进入"sleep模式"
}

//函数功能:中断唤醒后,程序会继续执行main()中的其它语句
//通过WFI进入的"sleep模式",退出方式是:只能是中断
void EnterSLEEPMode_With_WFI(void)
{
	__HAL_RCC_PWR_CLK_ENABLE();
	//PWR时钟使能
	//这一句不能少,否则,不能进入"sleep模式"

  HAL_PWR_DisableSleepOnExit();
	//则令SLEEPONEXIT位置0;
	//如果执行WFI,则立即进入"sleep模式"

	HAL_PWR_EnableSEVOnPend();
	//当"SEVONPEND=1"时,允许事件唤醒内核(包括中断唤醒)
	//这一句不能少,否则,事件无法唤醒CPU

  HAL_PWR_EnterSLEEPMode(PWR_SLEEPENTRY_WFI);
	//令SLEEPDEEP=0,然后执行WFI,令CPU进入"sleep模式"
}

//函数功能:中断唤醒后,程序只执行"相应的中断服务程序",退出中断后,会再次进入"sleep模式";
//SLEEPONEXIT位置1,通过WFE进入的"sleep模式",退出方式是:只能是中断
void EnterSLEEPMode_With_WFE_And_After_Interrupt(void)
{
	__HAL_RCC_PWR_CLK_ENABLE();
	//PWR时钟使能
	//这一句不能少,否则,不能进入"sleep模式"
	HAL_PWR_EnableSleepOnExit();
	//则令SLEEPONEXIT位置1,若执行WFE,则立即进入"sleep模式";当有中断发生后,则执行完中断服务程序,会继续进入"sleep模式"
  HAL_PWR_EnterSLEEPMode(PWR_SLEEPENTRY_WFE);
	//令SLEEPDEEP=0,然后执行WFE,令CPU进入"sleep模式"
}

//函数功能:中断唤醒后,程序只执行"相应的中断服务程序",退出中断后,会再次进入"sleep模式";
//SLEEPONEXIT位置1,通过WFI进入的"sleep模式",退出方式是:只能是中断
void EnterSLEEPMode_With_WFI_And_After_Interrupt(void)
{
	__HAL_RCC_PWR_CLK_ENABLE();
	//PWR时钟使能
	//这一句不能少,否则,不能进入"sleep模式"
	HAL_PWR_EnableSleepOnExit();
	//则令SLEEPONEXIT位置1,若执行WFI,则立即进入"sleep模式";当有中断发生后,则执行完中断服务程序,会继续进入"sleep模式"
  HAL_PWR_EnterSLEEPMode(PWR_SLEEPENTRY_WFI);
	//令SLEEPDEEP=0,然后执行WFI,令CPU进入"sleep模式"
}
#include "py32f0xx_hal.h"
#include "SystemClock.h"
#include "delay.h"
#include "LED.h"
#include "SystemClock.h"
#include "USART2.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "string.h" //使能strcpy(),strlen(),memset()
#include "EXTI.h"
#include "SleepMode.h"

const char CPU_Reset_REG[]="\r\nCPU reset!\r\n";
const char CPU_Run_REG[]="\r\nCPU run!\r\n";
int main(void)
{
	HSE_Config();
//	HSI_Config();
//	HAL_Init();//systick初始化
  delay_init();
  HAL_Delay(1000);
	USART2_Init(115200);
//PA0是为USART2_TX,PA1是USART2_RX
//中断优先级为0x01
//波特率为115200,数字为8位,停止位为1位,无奇偶校验,允许发送和接收数据,只允许接收中断,并使能串口
	printf("%s",CPU_Reset_REG);
	HAL_Delay(1000);
	printf("%s",CPU_Run_REG);

	MCU_LED_Init();
	HAL_SuspendTick();//systick中断关闭,防止systick中断唤醒
	EXTI12_Init();//将PA12引脚配置为外部中断引脚
	printf("SLEEP MODE!\n\n");

    EnterSLEEPMode_With_WFE();
//	EnterSLEEPMode_With_WFI();
//	EnterSLEEPMode_With_WFE_And_After_Interrupt();
//	EnterSLEEPMode_With_WFI_And_After_Interrupt();

  __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_12);//清除外部事件标志位
	//清除"GPIO_PIN_12外部事件标志位"
	//当软件或者硬件产生上升沿/下降沿触发事件时,该位置位;
	NVIC_ClearPendingIRQ(EXTI4_15_IRQn);//清除EXTI4_15_IRQn中断源的中断标志位

  HAL_ResumeTick();//systick中断开启
  printf("WAKEUP OK!\n\n");
  while (1)
  {
		HAL_Delay(500);
		MCU_LED_Toggle();
		printf("1234567890\r\n");
  }
}

事件唤醒:

//函数功能:将PA12引脚配置为外部事件引脚
void EXTI12_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructureure;

  __HAL_RCC_GPIOA_CLK_ENABLE();  //GPIOA时钟使能

  GPIO_InitStructureure.Pin = GPIO_PIN_12;//选择第12脚
	GPIO_InitStructureure.Pull = GPIO_PULLUP;//引脚上拉被激活
  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_MEDIUM;//配置GPIO速度为中速
	GPIO_InitStructureure.Mode   = GPIO_MODE_IT_FALLING;//配置为下降沿检测模式
	HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	//根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	//因为使用了GPIO_MODE_IT_FALLING,所以使能了外部中断线


//	HAL_NVIC_SetPriority(EXTI4_15_IRQn,0x0F,0);
	//EXTI4_15_IRQn表示外部中断线4~中断线15,EXTI4_15_IRQn
	//设置中断优先级为0x0F,0无意义,注意:0<=PreemptPriority<=3,值越大,表示中断优先级越低
	//Enable and set Button EXTI Interrupt to the lowest priority

//	HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
	//EXTI4_15_IRQn表示外部中断线4~中断线15,EXTI4_15_IRQn
	//使能EXTI4_15_IRQn中断
}

中断唤醒

//函数功能:将PA12引脚配置为外部中断引脚
void EXTI12_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructureure;

  __HAL_RCC_GPIOA_CLK_ENABLE();  //GPIOA时钟使能

  GPIO_InitStructureure.Pin = GPIO_PIN_12;//选择第12脚
	GPIO_InitStructureure.Pull = GPIO_PULLUP;//引脚上拉被激活
  GPIO_InitStructureure.Speed = GPIO_SPEED_FREQ_MEDIUM;//配置GPIO速度为中速
	GPIO_InitStructureure.Mode   = GPIO_MODE_IT_FALLING;//配置为下降沿检测模式
	HAL_GPIO_Init(GPIOA, &GPIO_InitStructureure);
	//根据GPIO_InitStructureure结构变量指定的参数初始化GPIOA的外设寄存器
	//因为使用了GPIO_MODE_IT_FALLING,所以使能了外部中断线


	HAL_NVIC_SetPriority(EXTI4_15_IRQn,0x03,0);
	//EXTI4_15_IRQn表示外部中断线4~中断线15,EXTI4_15_IRQn
	//设置中断优先级为0x03,0无意义,注意:0<=PreemptPriority<=3,值越大,表示中断优先级越低
	//Enable and set Button EXTI Interrupt to the lowest priority

	HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
	//EXTI4_15_IRQn表示外部中断线4~中断线15,EXTI4_15_IRQn
	//使能EXTI4_15_IRQn中断
}

三、事件唤醒测试结果

PY32F003F18之sleep模式_第1张图片

你可能感兴趣的:(产品研发,PY32F003F18,sleep模式,ARM,检验分享,唤醒,低功耗)