历史上的今天
返回首页

历史上的今天

今天是:2025年08月20日(星期三)

正在发生

2019年08月20日 | stm32之电源管理(实现低功耗)

2019-08-20 来源:eefocus

前言:STM32F10xxx系列产品都有电源管理模块,芯片功耗会影响到一个产品的续航能力;比如在一些终端传感器场合里,为了减轻后期的维护投入,要求长期工作时间较长,更需要合理的芯片功耗管理。芯片自带几种运行模式,包括正常模式、睡眠模式、停止模式、待机模式。越往后,芯片的功耗越低,但能执行功能就越少。低功耗的电源管理策略就是在芯片不需要对外界响应的时候进入低功耗模式,而当外界条件满足的时候,退出低功耗模式(唤醒),正常执行处理工作。下面对其模式之间的转换和各个模式下的芯片内部的运转情况等一探究竟。


写代码前要先了解芯片的特性及工作原理,难免会先阅读一些长长的文档。下面核心讲解一些要点。


1.硬件原理

下图是芯片的电源框架:


图左边7个电压点对应芯片的7个引脚,在芯片电路原理图能找到对应的引脚。


 、:是ADC转换器的参考电压,有些芯片没有这连个引脚,内部已经把他们接到、了。


、:是ADC转换器的供电电源,独立电源供电是为了过滤和屏蔽来自印刷电路板上的毛刺干扰,提高转换的精确度。(也可以直接连到、)。


、:STM32的工作电压(VDD)为2.0~3.6V。通过内置的电压调节器提供所需的1.8V电源。


:使用电池或其他电源连接到VBAT脚上,当VDD断电时,可以保存备份寄存器的内容和维持RTC的


功能。(如果没有外部电池,好像不接也可以,但是数据手册说必须接到)。


电池备份区域:


当备份区域由VDD(内部模拟开关连到VDD)供电时,下述功能可用:


    ● PC14和PC15可以用于GPIO或LSE(低速外部时钟)引脚


    ● PC13可以作为通用I/O口、TAMPER引脚、RTC校准时钟、RTC闹钟或秒输出


当后备区域由VBAT供电时(VDD消失后模拟开关连到VBAT),可以使用下述功能:


    ● PC14和PC15只能用于LSE(低速外部时钟)引脚


    ● PC13可以作为TAMPER引脚、RTC闹钟或秒输出


电压调节器:


复位后调节器总是使能的。根据应用方式它以3种不同的模式工作。


     ● 运转模式:调节器以正常功耗模式提供1.8V电源(内核,内存和外设)。


     ● 停止模式:调节器以低功耗模式提供1.8V电源,以保存寄存器和SRAM的内容。


     ● 待机模式:调节器停止供电。除了备用电路和备份域外,寄存器和SRAM的内容全部丢失。


2.低功耗模式

STM32F10xxx有三种低功耗模式:


     ● 睡眠模式(Cortex™-M3内核停止,所有外设包括Cortex-M3核心的外设,如NVIC、系统时钟(SysTick)等仍在运行)


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


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


此外,在运行模式下,可以通过以下方式中的一种降低功耗:


● 降低系统时钟


● 关闭APB和AHB总线上未被使用的外设时钟。


注意:在睡眠模式、停止模式及待机模式中,若备份区域电源正常供电,备份区域的RTC都可以正常运行、备份区域内的寄存器及备份区域内的SRAM数据会被保存,不受功耗模式影响。


3.睡眠模式实验

下面代码利用编译器内置函数__WFI()进入睡眠,任何中断将退出睡眠(实验使用串口中断和外部中断)。利用串口将芯片状态信息发送出来。可以先把代码复制到工程编译下载,实验现象通过串口上位机观察,如果有可调电源的话,可以对比正常工作和睡眠模式下的电流大小,正常来说睡眠模式下功率低,那么电流会比正常工作下低。下面程序并不复杂,程序进入while循环延时一段时间就会进入睡眠状态,利用上位机向串口发送数据或者将PA.0引脚接电源都可产生中断,从而退出睡眠模式。


#include "stm32f10x.h"

#include "stdio.h"

 

static void EXTI_Key_Config(void);

static void NVIC_Configuration(void);

static void USART1_Config(void);

static void Delay(__IO u32 nCount);

 

int main(void)

{

        USART1_Config();

EXTI_Key_Config();

//配置中断控制器NVIC

        NVIC_Configuration();

while(1)

{

printf("STM32正常运行.rn");

Delay(0xfffff);

//NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT,DISABLE);//调用__WFI时立即进入睡眠

NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT,ENABLE);//调用__WFI时,等待系统从最低优先级的中断处理程序中退出后进入睡眠

printf("STM32进入睡眠.rn");

__WFI();//WFI指令进入睡眠

//开始等待中断唤醒

Delay(0xfffff);

printf("已退出睡眠模式.rn");

        }

}

 

static void EXTI_Key_Config(void)

{

        GPIO_InitTypeDef GPIO_InitStructure;

    EXTI_InitTypeDef EXTI_InitStructure;

//开启外设时钟

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);

        //初始化 GPIOA.0 设置为下拉输入

  GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; 

  GPIO_Init(GPIOA, &GPIO_InitStructure);

//GPIOA.0 中断线配置

  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);

        //GPIOA.0 中断初始化配置

  EXTI_InitStructure.EXTI_Line=EXTI_Line0;

  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;//上升沿时进入中断

  EXTI_InitStructure.EXTI_LineCmd = ENABLE;

//初始化外设EXTI寄存器

  EXTI_Init(&EXTI_InitStructure);

}

 

void USART1_Config(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

//配置串口1(USART1)时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

       //配置串口1(USART1 Tx (PA.09))

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);

  

//配置串口1 USART1 Rx (PA.10)

       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA, &GPIO_InitStructure);

//串口1模式(USART1 mode)配置 

USART_InitStructure.USART_BaudRate = 9600;//一般设置为9600;

USART_InitStructure.USART_WordLength = USART_WordLength_8b;

USART_InitStructure.USART_StopBits = USART_StopBits_1;

USART_InitStructure.USART_Parity = USART_Parity_No ;

USART_InitStructure.USART_HardwareFlowControl =         USART_HardwareFlowControl_None;

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

USART_Init(USART1, &USART_InitStructure);

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断

USART_Cmd(USART1, ENABLE); //使能串口 

}

 

int fputc(int ch, FILE *f)//重写标准库的fputc函数

{

//将Printf内容发往串口

USART_SendData(USART1, (unsigned char) ch);

while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);

return (ch);

}

 

static void NVIC_Configuration(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);//使能外部中断 PA.0

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  

NVIC_Init(&NVIC_InitStructure);//使能串口1中断

}

 

void Delay(__IO u32 nCount) //简单的延时函数

{

for(; nCount != 0; nCount--);

在stm32f10x_it.c文件加入:


#include "delay.h"

void EXTI0_IRQHandler(void)

{     

Delay(0xFFFFF);//防抖

        //检查指定的EXTI0线路触发请求发生与否

        if(EXTI_GetITStatus(EXTI_Line0) != RESET)   

{   

     printf("按键中断唤醒.rn");

}

//清除EXTI0线路挂起位

EXTI_ClearITPendingBit(EXTI_Line0);  

}

 

void USART1_IRQHandler(void)

{

unsigned char code;

if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

{

    code=USART_ReceiveData(USART1);

            printf("串口中断唤醒.rn");

        }

睡眠模式的各种特性

image.png?imageView2/2/w/550

注意:在系统处于睡眠低功耗模式(包括后面介绍的停止模式、待机模式)时,不能用下载器进行程序下载,所以下载程序时要先把系统唤醒。或者使用如下方法:按着板子的复位键,点击电脑端的“下载”,然后松开复位键,就能正常给板子下载程序了。


4.停止模式实验

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


停止模式的功耗比睡眠模式更低,代码操作上相对比睡眠模式复杂一点。跟睡眠模式的唤醒不同,只有EXTI线的中断才能退出停止模式,因为其他外设在停止模式时被关闭,并不能响应中断。将mani函数替换为下面代码,其他不变:


int main(void)

{

        USART1_Config();

EXTI_Key_Config();

        NVIC_Configuration();//配置中断控制器NVIC

 

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能电源管理单元的时钟

while(1)

{

printf("STM32正常运行.rn");

Delay(0xfffff);

printf("STM32进入停止模式.rn");

PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFI);//进入停止模式,设置电压调节器为低功耗模式,等待中断唤醒

//PWR_EnterSTOPMode(PWR_Regulator_ON,PWR_STOPEntry_WFI);//进入停止模式,设置电压调节器为正常模式,等待中断唤醒

//开始等待任意EXTI线中断唤醒

SystemInit();//唤醒后需要恢复系统时钟,因为退出停止模式后,系统默认使用的HSI作为系统时钟

/*实际上在运行main函数前,会先执行SystemInit函数以配置系统时钟,这个在启动文件里可以看到。*/

                //刚退出停止模式时,使用HSI作为系统时钟,回影响串口波特率

                //输出不对,在重新配置时钟后才能使用串口的输出

Delay(0xfffff);

printf("已退出停止模式.rn");

          }

}

停止模式的各种特性

image.png?imageView2/2/w/550


5.待机模式实验

待机模式可实现系统的最低功耗。该模式是在Cortex-M3深睡眠模式时关闭电压调节器。整个1.8V供电区域被断电。PLL、HSI和HSE振荡器也被断电。SRAM和寄存器内容丢失。只有备份的寄存器和待机电路维持供电。也就是说从待机模式唤醒后,由于没有之前代码的运行记录,只能对芯片复位,重新检测boot条件,从头开始执行程序。它有4种唤醒方式,分别是WAUP(PA0)引脚的上升沿、RTC闹钟事件、NRST引脚的复位和IWDG(独立看门狗)复位。


我们不需要对PA.0引脚进行如上面的初始化,也不需要初始化一个外部中断,将下面两个函数替换,其余保持不变:


int main(void)

{

        USART1_Config();

//EXTI_Key_Config();

//配置中断控制器NVIC

        NVIC_Configuration();

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);//使能电源管理单元的时钟

if(PWR_GetFlagStatus(PWR_FLAG_WU)){

printf("rn待机模式复位.rn");

}else{

printf("rn非待机模式复位.rn");

}

while(1)

{

printf("STM32正常运行.rn");

Delay(0xfffff);

printf("STM32进入待机模式.rn");

PWR_ClearFlag(PWR_FLAG_WU);//清除唤醒标志状态

PWR_WakeUpPinCmd(ENABLE);//使能Wake引脚的唤醒功能,使能PA0

PWR_EnterSTANDBYMode();//进入待机模式

          }

}

 

static void NVIC_Configuration(void)

{

        NVIC_InitTypeDef NVIC_InitStructure;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  //NVIC_Init(&NVIC_InitStructure);//使能外部中断 PA.0

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  

NVIC_Init(&NVIC_InitStructure);//使能串口1中断

}

程序下载后,按下复位键,串口会打印非待机模式复位,接着运行while函数,延时后进入待机模式,等待唤醒,在PA0引脚给上升沿信号,串口打印已待机模式复位,代码重头开始执行。


待机模式的各种特性

image.png?imageView2/2/w/550

最后,除了利用上面三种模式实现低功耗外,还可以在运行模式下,关闭某些外设时钟或者利用分频器降低外设时钟,同样也可以减低系统功耗。电池备份区域部分这里没有细说,后面单独一篇介绍。


推荐阅读

史海拾趣

HOPERF公司的发展小趣事

在无线射频和传感器领域,HOPERF始终保持着技术创新的领先地位。公司独创的“NextGenRF”算法专利技术,填补了国内在该领域的空白,并获得了多项企业认证、发明专项和软件著作权。这些技术创新不仅推动了公司产品性能的持续提升,还引领了整个行业的发展方向。此外,HOPERF还积极参与国际标准制定,不断提升自身在全球行业中的话语权和影响力。

Crystal Clear Technology公司的发展小趣事

随着环保意识的日益增强,Crystal Clear Technology积极响应国家号召,将环保理念融入产品研发和生产过程中。公司采用环保材料和节能技术,降低产品对环境的污染。同时,公司还加强废弃物处理和资源回收利用,努力实现可持续发展。这一举措不仅提升了公司的社会形象,也为公司的长期发展奠定了坚实基础。

GWP Group公司的发展小趣事

Crystal Clear Technology自创立之初,便专注于研发新型显示技术。面对市场上日益增长的高清显示需求,公司投入大量资源进行技术研发,成功推出了一款具有高清晰度和广视角的显示屏产品。这一创新产品迅速获得市场认可,为Crystal Clear Technology打开了新的销售渠道,并奠定了公司在行业内的技术领先地位。

DSMI Electronics SA公司的发展小趣事

为了进一步扩大市场份额,DSMI Electronics SA公司开始实施全球化战略。公司积极拓展海外市场,通过参加国际展会、建立海外销售网络等方式,将产品销往全球各地。同时,DSMI还注重本土化经营,根据不同市场的特点和需求,调整产品策略和营销方式。这些努力使DSMI在国际市场上取得了显著的成绩。

Hirect公司的发展小趣事
考虑工作环境和安全性要求,选择合适的绝缘等级。
ATC [American Technical Ceramics]公司的发展小趣事

随着全球经济的日益一体化,国际合作成为许多公司拓展市场的重要途径。假设ATC在某次国际技术交流会上与一家欧洲知名电子企业达成了合作协议,双方共同开发了一款新型陶瓷电容器。这款电容器不仅性能卓越,而且成本相对较低,因此在全球市场上受到了广泛的欢迎。通过这次合作,ATC不仅提升了自身的技术实力,也进一步拓展了海外市场。

问答坊 | AI 解惑

基于DSP和FPGA的信号采集的设计与实现

基于DSP和FPGA的信号采集的设计框图和实现代码…

查看全部问答>

太阳能给锂电池充电,出现爆裂,不知怎么回事

锂电池加了充电保护,电池12.60v,太阳能板标准16v,5w(实际肯定达不到)…

查看全部问答>

免费实验室申请

前段时间看到东方集成提供这个服务,提供免费实验室,详细http://www.jicheng.net.cn/rental/cart/lab_apply.html 分享给大家,有实际用过的希望给讲讲内幕…

查看全部问答>

串口通信中遇到的问题

CPU是STM32F103CB,无操作系统。 通过UART1接受GPRS发来的数据,在中断函数中 USART1_IRQHandler 中进行处理 unsigned char a_GPRSData[500]; unsigned int  g_DataLength; void USART1_IRQHandler(void)        ...…

查看全部问答>

MPLAB编译问题

Clean: Deleting intermediary and output files. Clean: Deleted file \"C:\\Program Files\\Microchip\\lzz1\\lzz001.cce\". Clean: Done. Executing: \"C:\\HT-PIC\\BIN\\PICC.EXE\" -C -E\"lzz001.cce\" \"lzz001.c\" -O\"lzz001.obj\" -Q - ...…

查看全部问答>

有一个病毒高手帮我做掉它!

是一个U盘感染的病毒,在D盘中出现一个autorun.inf文件,同时点D盘右健会多一个\"浏览\"项,而这个文件的内容是: [autorun] open=.\\recycled\\info.exe shell\\1=浏览 shell\\1\\Command=.\\recycled\\info.exe shellexecute=.\\recycled\\info. ...…

查看全部问答>

DS18b20温度显示问题

#include sbit ds=P3^7; //0-F数码管显示(共阴) unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //0-9数码管的显示,共阴带小数点 unsigned char code tabledot[]={ ...…

查看全部问答>

关于nios烧写问题、求大神帮助

使用的是ep2s180f1020i4的片子,配置芯片epcs64,用flash programmer 进行烧写,从状态栏来看 烧写成功了,但是上电后没有任何反应,不止nios没跑起来,连逻辑都没烧进去,但是在线运行时是正常的,单独烧写逻辑从新上电也是可以起来的,就是用nios ...…

查看全部问答>

第一版开关电源(新手入门,大神勿喷!)

经过再三调试,我人生的第一版开关电源诞生了,激动ing,不过也仍有很多问题没有解决!希望高手指教!这里好像不能传附件啊,详细过程在下面链接里面了,有兴趣的亲可以看看,多多指教!…

查看全部问答>