STM32低功耗模式–停止模式

STM32F10xx低功耗模式

  • 睡眠模式:Cortex™-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时钟(SysTick)等仍在运行
  • 停止模式:所有的时钟都已停止
  • 待机模式:1.8V电源关闭

STM32F10X停止模式的配置

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

  • 进入停止模式:
    在停止模式下,通过设置电源控制寄存器(PWR_CR)的LPDS位使内部调节器进入低功耗模式,能够降低更多的功耗。
    如果正在进行闪存编程,直到对内存访问完成,系统才进入停止模式。
    如果正在进行对APB的访问,直到对APB访问完成,系统才进入停止模式。
    在配置停止模式时,以下功能能需要独立进行编程:
  • 独立看门狗(IWDG)一旦启动除非系统复位,它不能再被停止;
  • 实时时钟(RTC)需要单独通过备份欲寄存器(RCC_DBCR)的RTCEN来设置
  • 内部RC振荡器(LSI RC):通过控制/状态寄存器 (RCC_CSR)的LSION位来设置。
  • 外部32.768kHz振荡器(LSE):通过备份域控制寄存器 (RCC_BDCR)的LSEON位设置。
  • 在停止模式下,如果在进入该模式前ADC和DAC没有被关闭,那么这些外设仍然消耗电流。通过设置寄存器ADC_CR2的ADON位和寄存器DAC_CR的ENx位为0可关闭这2个外设。
  • 配置步骤
    1、设置Cortex-M3系统控制寄存器中的SLEEPDEEP位(SCB_SCR参考Cortex-M3权威指南182页)。
    2、 清除电源控制寄存器(PWR_CR)中的PDDS位。
    3、通过设置PWR_CR中LPDS位选择电压调节器的模式
    4、执行WFI或者WFE汇编指令
    注:为了进入停止模式,所有的外部中断的请求位(挂起寄存器(EXTI_PR))和RTC的闹钟标志都必须被清除,否则停止模式的进入流程将会被跳过,程序继续运行。
//THUMB指令不支持汇编内联
//采用如下方法实现执行汇编指令WFI,等待下一个外部中断触发
void WFI_SET(void)
{
	__ASM volatile("wfi");		  
}
/******************进入停止模式*********************/
void SYS_StopMode(void)
{
	SCB->SCR|=1<<2;//使能SLEEPDEEP位 Cortex-M3权威指南182页
	RCC->APB1ENR|=1<<28; //使能电源时钟
	PWR->CR&=~(1<<1);//进入停机模式
	PWR->CR|=1<<0;//在停机模式下电压调压器处于低功耗模式
	WFI_SET();
}

  • 当一个中断或唤醒事件导致退出停止模式时, HSI RC振荡器被选为系统时钟。
  • 当电压调节器处于低功耗模式下,当系统从停止模式退出时,将会有一段额外的启动延时。如果在停止模式期间保持内部调节器开启,则退出启动时间会缩短,但相应的功耗会增加。
  • 配置步骤
    1、如果执行WFI进入停止模式:设置任一外部中断线为中断模式(在NVIC中必须使能相应的外部中断向量)。
    2、如果执行WFE进入停止模式:设置任一外部中断线为事件模式。
    这里以WFI模式为例,通过外部中断线2下降沿触发退出停止模式:
    从停止模式退出时HSI RC振荡器将作为系统时钟。为了保证从停止模式退出后各项功能可以正常使用我们需要重新配置系统时钟。
/*系统时钟配置*/
void STM32_Clock_Init(u8 PLL)
{
	u8 temp;
	RCC->CR|=1<<16;//开启HSE时钟
	while(!(RCC->CR>>17));//等待外部时钟就绪
	RCC->CFGR|=0x4<<8;//APB1时钟由系统时钟2分频
	PLL-=2;//实际倍频数和填入参数差2,9倍频写入的数值为7
	RCC->CFGR|=PLL<<18;//PLL时钟9倍频
	RCC->CFGR|=1<<16;	  //HSE作为PLL时钟输入源
	FLASH->ACR|=0x32;	  //FLASH 2个延时周期
	RCC->CR|=1<<24;//PLL时钟使能
	while(!(RCC->CR>>25));//等待PLL锁定
	RCC->CFGR|=0x2<<0;//PLL输出作为系统时钟
	while(1)
	{
		temp=(RCC->CFGR>>2)&0x3;
		if(temp==0x2)break;
	}	
}
/********************退出停止模式***********************/
void SYS_ExitStopMode(void)
{
	RCC->APB2ENR|=1<<0;//AFIO
	/*PA5配置外部中断模式*/
	AFIO->EXTICR[0]|=(0X4<<2*4);//PE2作为外部中断5输入源
	EXTI->IMR|=1<<2;//开启EXTI2中断请求
	EXTI->FTSR|=1<<2;//允许EXTI2下降沿触发
	STM32_NVIC_SetPriority(EXTI2_IRQn,1,1);//设置优先级		
}
void EXTI2_IRQHandler(void)
{
	STM32_Clock_Init(9);//时钟配置,从停止模式唤醒时默认选择的为HSI作为系统时钟源
	printf("退出停止模式\r\n");
	EXTI->PR|=1<<2;//清除标志
}
  • 主函数实现
    通过按键进入停止模式,外部中断2下降沿触发退出停止模式。
int main()
{
	u16 cnt=0;
	u8 key=0;
	Beep_Init();
	Led_Init();
	Key_Init();
	SYS_ExitStopMode();
	Usartx_Init(USART1,115200,72);
	TIMx_Init(TIM2,72,20*1000);
	printf("USART1初始化完成\r\n");
	while(1)
	{
		Delay_Ms(1);
		cnt++;
		if(cnt>=500)
		{
			cnt=0;
			LED1=!LED1;
		}
		key=Key_Scan();
		if(key==1)
		{
			printf("进入停止模式\r\n");
			LED1=1;
			SYS_StopMode();
		}
		if(usart1_flag)
		{
			usart1_rx_buff[usart1_cnt]='\0';
			printf("USART1:%s\r\n",usart1_rx_buff);
			usart1_flag=0;
			usart1_cnt=0;
		}
	}
}