草庐IT

浅谈stm32的低功耗模式

lxyjrx 2023-03-28 原文

stm32标准库实现低功耗

一、概述

stm32不同系列芯片支持的低功耗模式各有差异,本文以F103系列芯片为例,简单讲解不同低功耗模式的特点和使用方法。

二、低功耗

简述

默认情况下,系统或电源复位后,微控制器处于Run模式。当CPU不需要保持运行时(例如等待外部事件时),可以使用几种低功耗模式来节省电源。这取决于用户选择的模式,以提供低功耗、较短启动时间和可用的唤醒源之间的最佳折衷。

stm32f10xxx 设备有三种低功耗模式:

  • 睡眠模式
    这种模式会关闭cpu时钟,但是所有外设包括M3内核的外设(NVIC、SysTick等等)都不会受到影响,保持运行
  • 停止模式
    所有时钟都会关闭
  • 待机模式
    1.8供电区域断电

另外,mcu在运行模式(run)下也可以通过以下方式降低功耗:

  • 降低系统时钟频率
  • 关闭一些不使用的外设的时钟

上面这三种低功耗模式的具体描述可以看下面这个图,觉得阅读英文不方便的话请自行翻译,我觉得这更有助于你去理解这几个模式的特点。

下面这张表更好的汇总了各种低功耗模式的特点:

详细介绍

下面会简单介绍各种降低功耗的方法,包括run、sleep、stop、standby。

run模式下

1、Slowing down system clocks(run模式下降低功耗)

run模式下,我们可以通过对预分频器编程来降低系统时钟(SYSCLK, HCLK, PCLK1, PCLK2);
在进入sleep模式之前,我们也可以对预分频器编程来降低外设时钟。

详细请查阅RCC_CFGR寄存器,这里不展开描述。

2、 Peripheral clock gating(外围时钟门控)

在Run模式下,每个外设和存储器的HCLK和PCLKx可以随时停止,以降低功耗。
在sleep模式下,在执行WFI或者WFE内核指令之前我们可以关闭一些不需要使用的外设时钟来进一步降低功耗。

低功耗模式下(分为sleep、stop、standby)

1、sleep mode

进入sleep模式

通过执行WFI (Wait For Interrupt)或WFE (Wait For Event)指令进入Sleep模式。根据Cortex®-M3系统控制寄存器中的SLEEPONEXIT位,有两种选项可用于选择Sleep模式进入机制:

  • Sleep-now:如果清除SLEEPONEXIT位,则在执行WFI或WFE指令时,MCU马上进入Sleep模式。

  • Sleep-on-exit:如果设置了SLEEPONEXIT位,则MCU在退出最低优先级ISR时进入Sleep模式。

    在休眠模式下,所有I/O引脚保持与运行模式相同的状态。

退出sleep模式

如果使用WFI指令进入睡眠模式,任何被NVIC确认的外设中断都可以从睡眠模式唤醒设备。

如果使用WFE指令进入Sleep模式,则在事件发生时,MCU将立即退出Sleep模式。唤醒事件可以通过以下任意一种方式产生:

  • 在外设控制寄存器中启用中断,但在NVIC中不启用,并在Cortex®-M3系统控制寄存器中启用SEVONPEND位。当MCU从WFE恢复时,必须清除外设中断悬挂位(pending)和外设NVIC IRQ通道悬挂位(pending)(在NVIC中断清除悬挂寄存器中)。

  • 在事件模式下配置外部或内部EXTI line。当CPU从WFE恢复时,由于事件行对应的挂起位没有设置,不需要清除外设中断挂起位或NVIC IRQ通道挂起位。

所有进入和退出休眠的细节汇总成以下表格:

2、stop mode

简述

停止模式是基于Cortex®-M3深度睡眠模式结合外围时钟门控。电压调节器可以配置在普通模式或低功率模式。

在停止模式下,1.8 V域中的所有时钟都停止,锁相环、HSI和HSE RC振荡器都被禁用。SRAM和寄存器的内容被保留。

在停止模式下,所有I/O引脚保持与运行模式相同的状态。

进入停止模式
  • 为了进一步减少功耗,可以设置电压调节器工作在低功耗模式,这需要配置PWR_CR的LPDS位。
  • 如果闪存编程正在进行,停止模式的进入将被延迟,直到内存访问完成。
  • 如果对APB域的访问正在进行,停止模式的进入将延迟到对APB的访问完成。

在停止模式下,可以通过编程单个控制位来选择以下特性:

  • Independent watchdog (IWDG)
  • Real-time clock (RTC)
  • Internal RC oscillator (LSI RC)
  • External 32.768 kHz oscillator (LSE OSC)

此外,ADC或DAC在停止模式下也会消耗电能,除非他们在进入停止模式之前被禁用。
要禁用它们,ADC_CR2寄存器中的ADON位和DAC_CR寄存器中的ENx位必须都写为0。

退出停止模式

当通过发出中断或唤醒事件退出Stop模式时,HSI RC振荡器被选为系统时钟。

当电压调节器在低功率模式下运行时,当从停止模式唤醒时,会产生额外的启动延迟。通过在停止模式期间保持内部调节器(这里是指电压调节器)处于ON状态,虽然减少了启动时间,但消耗更高。

下图汇总了停止模式进入和退出的细节信息。

注意:

  1. 在进入停止模式之前,要清除所有中断挂起位,如上图所述。
  2. 唤醒之后记得要重新配置系统时钟。

3、Standby mode

简述

“待机”模式可以实现最低的功耗。它基于Cortex®-M3深度睡眠模式,禁用电压调节器。导致1.8 V域下电。锁相环、HSI振荡器和HSE振荡器也处于关闭状态。除了备份域和备用电路中的寄存器外,SRAM和寄存器的内容都会丢失。

进入待机模式

在待机模式下,可以通过编程单个控制位来选择以下特性:

  • Independent watchdog (IWDG)
  • Real-time clock (RTC)
  • Internal RC oscillator (LSI RC)
  • External 32.768 kHz oscillator (LSE OSC)
退出待机模式

当外部复位(NRST引脚)、IWDG复位、WKUP引脚上升沿或RTC告警上升沿发生时,微控制器退出待机模式。
除电源控制/状态寄存器(PWR_CSR)外,所有寄存器都在Standby唤醒后重置。

从待机模式唤醒后,程序跟复位后一样重新启动。电源控制/状态寄存器(PWR_CSR)中的SBF状态标志表示MCU处于待机模式。所以程序重新运行后我们可以读取这个状态标志SBF来判断是否从待机模式唤醒。

下图汇总了待机模式进入和退出的细节信息。

注意:
在待机模式下,所有I/O引脚都是高阻态的,除了:

  • 复位引脚(仍可用)
  • 干预引脚,如果配置为干预或校准输出
  • WKUP引脚,如果使能了

调试模式

默认情况下,如果应用程序在调试功能使用时将MCU置于停止或待机模式,调试连接将丢失。这是因为Cortex®-M3内核停止工作了。

但是,通过在DBGMCU_CR寄存器中设置一些配置位,即使正在使用低功耗模式,也可以对软件进行调试。

核心不允许在调试会话期间关闭FCLK或HCLK。因为这些是调试器连接所需的,所以在调试期间,它们必须保持活动状态。单片机集成了特殊的方法,允许用户在低功耗模式下调试软件。为此,调试器主机必须首先设置一些调试配置寄存器来改变低功耗模式的行为:

  • 在Sleep模式下,DBGMCU_CR寄存器的DBG_SLEEP位必须事先由调试器设置。这将提供给HCLK与提供给FCLK相同的时钟(系统时钟以前由软件配置)。

  • 在停止模式下,DBG_STOP位必须由调试器预先设置。这将
    使内部RC振荡器时钟在停止模式下供给FCLK和HCLK。

这里不开展描述,有兴趣请参考相关用户手册。

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

RTC可以用来从低功耗模式唤醒MCU,而不依赖外部中断(自动唤醒模式)。
RTC提供了一个可编程的时间基准,从停止或待机模式在定期间隔唤醒。
为此,可以通过对备份域控制寄存器(RCC_BDCR)中的RTCSEL[1:0]位进行编程来选择三个RTC时钟源中的两个,如下图:

  • 32.768 kHz外部晶体振荡器(LSE OSC)。该时钟源提供了精确的时间基准,功耗极低(典型情况下增加不超过1µa)。

  • RC内部振荡器(LSI RC)。该时钟源具有节省32.768 kHz晶体成本的优点。这种内部RC振荡器的设计是为了增加最小的功耗。

要使用RTC闹钟事件从Stop模式唤醒,需要:
1、将EXTI Line 17设置为对上升沿敏感
2、配置RTC产生RTC闹钟
从Standby模式中唤醒,不需要配置EXTI Line 17。

下面汇总一些各个低功耗模式的特点和使用方法:

总结

本文简单介绍了STM32F1系列低功耗模式的特点和使用方法,使本人加深了对这些低功耗模式涉及的对象的理解,便于后续的低功耗设计和应用。
好记性不如烂笔头。

参考资料

参考手册
datasheet
编程手册

有关浅谈stm32的低功耗模式的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  4. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  5. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  6. ruby-on-rails - environment.rb 中设置的常量在开发模式中消失 - 2

    了解Rails缓存如何工作的人可以真正帮助我。这是嵌套在Rails::Initializer.runblock中的代码:config.after_initializedoSomeClass.const_set'SOME_CONST','SOME_VAL'end现在,如果我运行script/server并发出请求,一切都很好。然而,在我的Rails应用程序的第二个请求中,一切都因单元化常量错误而变得糟糕。在生产模式下,我可以成功发出第二个请求,这意味着常量仍然存在。我已通过将以上内容更改为以下内容来解决问题:config.after_initializedorequire'some_cl

  7. Ruby:标准递归模式 - 2

    我经常迷上ruby​​的一件事是递归模式。例如,假设我有一个数组,它可能包含无限深度的数组作为元素。所以,例如:my_array=[1,[2,3,[4,5,[6,7]]]]我想创建一个方法,可以将数组展平为[1,2,3,4,5,6,7]。我知道.flatten可以完成这项工作,但这个问题是作为我经常遇到的递归问题的一个例子-因此我试图找到一个更可重用的解决方案。简而言之-我猜这种事情有一个标准模式,但我想不出任何特别优雅的东西。任何想法表示赞赏 最佳答案 递归是一种方法,它不依赖于语言。您在编写算法时要考虑两种情况:再次调用函数的情

  8. ruby - 在 Ruby 中查找多个正则表达式匹配的模式和位置 - 2

    这应该是一个简单的问题,但我找不到任何相关信息。给定一个Ruby中的正则表达式,对于每个匹配项,我需要检索匹配的模式$1、$2,但我还需要匹配位置。我知道=~运算符为我提供了第一个匹配项的位置,而string.scan(/regex/)为我提供了所有匹配模式。如果可能,我需要在同一步骤中获得两个结果。 最佳答案 MatchDatastring.scan(regex)do$1#Patternatfirstposition$2#Patternatsecondposition$~.offset(1)#Startingandendingpo

  9. ruby - sinatra 框架的 MVC 模式 - 2

    我想开始使用“Sinatra”框架进行编码,但我找不到该框架的“MVC”模式。是“MVC-Sinatra”模式或框架吗? 最佳答案 您可能想查看Padrino这是一个围绕Sinatra构建的框架,可为您的项目提供更“类似Rails”的感觉,但没有那么多隐藏的魔法。这是使用Sinatra可以做什么的一个很好的例子。虽然如果您需要开始使用这很好,但我个人建议您将它用作学习工具,以对您来说最有意义的方式使用Sinatra构建您自己的应用程序。写一些测试/期望,写一些代码,通过测试-重复:)至于ORM,你还应该结帐Sequel其中(imho

  10. ruby-on-rails - Rails 如何创建数据模式种子数据 - 2

    有没有一种方法可以自动生成种子数据文件并创建种子数据,就像您在下面链接中的Laravel中看到的那样?LaravelDatabaseMigrations&Seed我在另一个应用程序上看到在Rails的db文件夹下创建了一些带有时间戳的文件,其中包含种子数据。创建它的好方法是什么? 最佳答案 我建议你使用Fabrication的组合gem和Faker.Fabrication允许您编写一个模式来构建您的对象,而Faker为您提供虚假数据,如姓名、电子邮件、电话号码等。这是制造商的样子:Fabricator(:user)dousernam

随机推荐