单片机的系统功耗控制/电源模式管理/AWU自动唤醒
功耗控制概述
低功耗的意义
-
节省资源
降低功耗就是省电,这不仅意味着节约了电力资源,也意味着提升续航时间,以及降低电磁辐射与热噪声对设备寿命的影响,延长了设备生命周期
-
低成本与小型化
降低功耗后就不必使用较大的散热模块以及电源模块,能降低系统的成本,也使系统能够更加紧凑小型化
降低系统功耗的方式
-
硬件调整
对硬件的选择或配置直接影响系统功耗,主要分以下方面
- 电源单元:电源的效率和质量直接关系到单片机的功耗与稳定性,电源应该效率高、发热小、纹波参数合理、性能足够使用
- 功能外设:外设应该尽可能选择低功耗的集成化器件,并合理设计供电电路和散热单元
- 电路设计:例如慎用上/下拉电阻,必须使用时合理选择阻值,避免不必要的电源消耗;暂未使用的端口要合理配置,不能随意连接到VDD/VSS等,这些设计细节都有助于减少开销
- 单片机选型:这是最重要的一点,要选择适合当前应用的单片机型号
-
软件优化
单片机系统中有一部分功耗是间接产生的,所谓间接是指不合理的控制逻辑或低效率的程序,这就需要对软件进行优化来降低功耗
- 注重程序的结构优化和编译优化:程序要选择合适的算法和数据结构、注重程序的时间/空间复杂度;编译器可以对源代码进行优化,还能调整优化等级,而这需要程序员写出编译器易于优化的代码
- 用程序实现替代简单的硬件单元:例如编码、译码和滤波等电路单元,用硬件搭建功耗较高,这时可以去掉这些硬件,用软件实现方法(在介绍按键去抖和ADC的章节中已经有介绍),而这种方法有利有弊,会牺牲一定的速度并对CPU性能提出更高要求
- 使用事件驱动机制:如果CPU一直进行大量运算和操作,功耗便会居高不下,因此在有数据要处理时才唤醒CPU,让其在短时间内完成处理后进入“休息”状态,最直接的便是用中断替代轮询
- 减少CPU运算工作量:这需要在程序上进行优化,比如处理数字信号时,有多种软件滤波算法,在精度允许的情况下要使用简单滤波替代复杂滤波;还有对于一些重复度较高的计算可以算好后使用查表法;尽量避免浮点数运算
STM8的功耗影响因素
-
供电电压
STM8核心电压为1.8V,支持3.3-5V的宽电压供电,显然使用3.3V供电时的STM8功耗会下降
-
代码执行位置
从RAM中执行代码比从Flash中执行的电源电流要小,因为RAM存取速度快,执行效率高
-
时钟源及频率
显然,频率高的时候功耗会更高
相同频率下,HSE石英晶体振荡器消耗电流比HSE外部信号输入方式更多,HSE时钟源又比HSI消耗电流高,HSI比LSI消耗高
-
片上外设
只启用需要的外设来节省功耗,即便所有的外设都要使用,也存在分时运行的情况
STM8上的耗电大户是ADC与定时器(功能越高级越耗电)
电源模式管理
STM8的电源模式分类
-
运行模式
运行模式是默认的模式,此模式下:CPU由fCPU提供运行时钟并执行程序,而fMASTER分别为其他激活的片上外设提供时钟,这时系统功耗可达最大
-
低功耗模式
但对于一些不需要CPU一直保持运行的需求,STM8提供三种低功耗的模式:
等待模式/活跃停机模式/停机模式
等待模式Wait
-
等待模式概述
等待模式中:CPU停止运行,但片上外设和中断控制器保持运行
等待模式下所有寄存器和RAM的内容保持不变,之前定义的时钟配置(寄存器CLK_CMSR的内容)也不会改变
可以通过配置外设设置门控PCG功能禁止片上外设时钟连接,切换低功耗时钟源这些操作来进一步降低功耗
-
进入等待模式
在运行模式下执行STM8的专用命令
WFI
,如下:void main() { //省略具体语句 asm("WFI");//从运行模式切换至等待模式 //省略具体语句 }
-
退出等待模式
可被所有的内部中断、AWU或者外部中断(包含中断输入的GPIO端口和通信外设中断等)以及复位事件唤醒,当一个中断请求产生时,CPU从等待模式退出并恢复工作
停机模式Halt
-
停机模式概述
停机模式中:关闭主电源调节器(只保留低功耗电源调节器和掉电复位工作),关闭时钟振荡,由fMASTER提供时钟的CPU和所有外设也都被关闭,是电流消耗最低的一种模式
停机模式下所有寄存器和RAM的内容保持不变,之前定义的时钟配置(寄存器CLK_CMSR的内容)也不会改变;
-
进入停机模式
使用命令
HALT
void main() { //省略具体语句 asm("HALT");//从运行模式切换至等待模式 //省略具体语句 }
-
退出停机模式
可以被外部中断和复位事件唤醒,内部中断与AWU不能唤醒
需要注意的是,HSE启动速度较慢,如果需要快速唤醒单片机电源,可以在进入停机模式前选择HSI作为fMASTER的时钟源;或者设置内部时钟寄存器CLK_ICKR_FHWU选择HSI时钟,这样就不需要再进行时钟切换了
另外单片机的Flash储存器在停机时处于掉电状态,其唤醒时间较长,如果想要快速唤醒可以将FLASH_CR1_HALT位置1,让Flash处于等待状态
活跃停机模式Acitce-Halt
-
活跃停机模式概述
开启主电压调节器,关闭时钟振荡,关闭CPU,外设只保留AWU开启;如果使能了AWU单元和独立看门狗IWDG,则LSI和HSE时钟源还处于运行状态
它和停机模式类似,但是不必通过外部中断唤醒,而是可以使用自动唤醒AWU,AWU会在一定延时后产生一个内部唤醒事件(本质上就是一个计数器)
-
进入活跃停机模式
进入活跃停机模式前,首先要使能AWU功能,再执行
HALT
停机命令 -
退出活跃停机模式
可被AWU、外部中断、复位事件唤醒
活跃停机模式下快速唤醒很重要,这需要同停机模式一样设置HSI时钟;
而Flash在活跃停机状态下默认就是工作状态,如果需要降低功耗,可以向FLASH_CR1_AHALT位置1,让活跃停机状态下停止向其供电,但如上文所述增加唤醒时间
AWU自动唤醒
AWU系统概述
-
AWU的作用
前文提到,AWU能够实现将STM8从活跃停机状态切换到运行状态,它就相当于一个定时闹钟,在预设的时间后唤醒单片机
-
AWU系统结构
AWU本质就是计数器(这和看门狗的原理类似),特殊之处在于其计时溢出时产生中断能够唤醒单片机,而且其只能使用LSI或者HSE晶振时钟源,
-
AWU的时钟
具体的时钟源选择由选项字节OPT4的CKAWUSEL位(OPT4的第2位)决定,置0为选择LSI作为时钟源,置1选择HSE为时钟源
事实上,无论选择那个时钟源,最后AWU使用的时钟都是固定的128kHz;如果使用HSE作为时钟源,就会多出一步分频(因为HSE的频率一般都较高),分频系数同样在选项字节OPT4中,其PRSC[1:0]位设定AWU时钟分频系数,具体分频情况如下:
- PRSC[1:0]=00:24MHz分频至128kHz
- PRSC[1:0]=01:16MHz分频至128kHz
- PRSC[1:0]=10:8MHz分频至128kHz
- PRSC[1:0]=11:4MHz分频至128kHz
AWU配置简述
-
配置时钟源
配置选项字节OPT4的CKAWUSEL位,置0选LSI,置1选择HSE;选择HSE则按其频率进行分频
-
修正时钟源
这一步会更详细地阐述,因为在时钟源一章中提到过,LSI存在的误差较大,而AWU又对计时精度有较高要求,所以进行修正很有必要,其流程如下:
- 将控制/状态寄存器AWU_CSR中的MSR位置1,把LSI内部时钟连接到TIM3或TIM1的捕获通道ICAP1上
- 通过定时器的输入捕获中断来测量频率
- 根据测量所得的频率来设定相关值,提高精度,具体配置方法见下文
-
配置时钟预分频
通过配置异步预分频寄存器APR[5:0]来配置适当的预分频值
-
配置自动唤醒延时间隔
通过配置时基选择寄存器AWU_TBR中的AWUTB[3:0]选择需要的自动唤醒时间间隔
-
使能AWU
置控制/状态寄存器AWU_CSR的AWUEN位为1
-
将单片机切换至活跃停机状态
执行HALT指令
AWU相关寄存器
-
控制/状态寄存器 AWU_CSR
用以使能AWU单元,使能测量功能,以及指示自动唤醒中断的有无
-
异步预分频寄存器 AWU_APR
设置分频值
-
时基选择寄存器 AWU_TBR
设置自动唤醒的时间间隔,如果不需要使用AWU,必须写0000到此寄存器来降低功耗
AWU的唤醒时间计算公式
-
AWU唤醒时间公式表
对AWU_APR寄存器配置APR分频值,对AWU_TBR寄存器配置AWUTB时基值,这两个参数对唤醒时间的影响参见此表
-
分频值APR的计算
例如:当前时钟频率为128kHz,要设定6ms唤醒,要求计算得到AWUTB与APR的配置值
从表中可见6ms在4-8ms范围内,其对应的一行中AWUTB=0101(即0x05)
而对应的APR计算公式为T=24×APR/f,变换公式得APR=(T×f)/24
将T=6×10-3s,f=128000Hz带入,得APR=48DEX(即0x30)
如果计算得到的是小数,要取近似值化为整数
代码实现
-
配置AWU单元
void AWU_init() { CLK_ICKR |= 0x0C;//打开LSI,从活跃停机状态快速唤醒使能 FLASH_CR1 |= 0x40;//活跃停机模式下FLASH不掉电 AWU_APR = 0x30;//配置预分频值 AWU_TRB = 0x05;//配置AWU唤醒时间间隔 AWU_CSR1 |= 0x10;//使能AWUEN位,启动AWU } void main() { //省略具体语句 AWU_init(); asm("HALT");//进入活跃停机 //省略具体语句 } #pragma vector=3 //AWU单元的中断处理函数 __interrupt void AWU_IRQHandler(void) { //省略具体语句 AWU_CSR1 |= 0x10; }
本文来自博客园,作者:无术师,转载请注明原文链接:https://www.cnblogs.com/untit1ed/p/18683775
本文使用知识共享4.0协议许可 CC BY-NC-SA 4.0
请注意: 特别说明版权归属的文章以及不归属于本人的转载内容(如引用的文章与图片)除外
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?