大家好,我是『芯知识学堂』的SingleYork,今天笔者要给大家分享一下有关低功耗产品设计的相关知识。
随着电子产品的越来越普及,尤其是很多电子产品都用上了电池供电,既然用电池供电,那么似乎我们就不得不考虑电池的续航能力的问题,进而,迫使我们不得不考虑电子产品功耗的问题。那么究竟怎样才算低功耗呢?小于100mA?小于1mA?小于10uA?似乎应该加上应用场合,这种数值才有意义。不管怎样,低功耗的意思可以概括为越小越小!
在做这个温度记录仪之前,笔者压根不怎么需要考虑功耗的问题,毕竟在一个大设备里,开关电源直接供电,控制板那100毫安以内的电流,几乎可以忽略不计了。然而,在做这个温度记录仪的时候,才发现,100mA的电流经得起多久的折腾?一块500mAh的锂电池,几个小时就没电了,更别说要用几十天甚至半年到一年的时间了。
当然,降低功耗并不是纯硬件或软件就能实现的,很多时候,都是需要软件和硬件的协同工作才能解决问题。比如,我们在做NTC测温电路的时候,如果直接如下图所示连接,那么实际上,计时在未进行AD采集的时候,改电路也一直在消耗电流,按照常温状态下来算,NTC的阻值为10K,那么这部分的电流消耗为:I=3.3V/(10K+10K)= 165uA。似乎看起来很小,但是,这只是电路中一部分的消耗,还有其他很多部分都有电流消耗,累加起来之后,就比这165uA大的多了。那么有没有办法让这一部分电路的功耗降低呢?答案肯定是有的。
比如,我们可以在3.3V电源部分或者GND部分加一个开关,并且通过一个IO口来直接控制这个开关,在需要进行AD采样的时候,把这个开关打开,采样完成后,再把这个开关关闭,这样一来,似乎就可以尽可能的减小这部分的开销了。那么以在GND端加一个MOS管为例,如下图所示:
这样一来,我们就可以达到之前预期的目的了。当然,如果真如上这样设计电路的话,无形中似乎也增加了成本,一个SI2302也需要一两毛钱,一个电阻也是几分钱,如果是几K甚至几十K的量的话,那么成本就不是一点点了。那么上述电路是不是还可以简化一下呢?那是必须滴!实际上我们可以直接通过一个IO口来接到NTC的一端,毕竟按照之前计算的电流,也才微安级别的,就算忽略掉NTC的阻值,也有R1起到限流的作用,不用担心烧坏IO口。那么,当需要采集AD的时候,直接将IO口拉低,就能实现电阻分压了。
由此可见,降低功耗从硬件角度来说,就是需要找到所有可能的消耗电路的回路,一一确定哪些是可以通过软件控制的方式来优化功耗的,哪些是避免不了的,并给编程人员提供一个所有IO口状态对功耗影响的关系,通常用简单的表格说明一下高电平会怎样,低电平会怎样,悬浮会怎样。做到这一点,基本上硬件的工作就告完成,剩下的就是软件开发人员的发挥空间了。
说到软件功耗优化,简单来说就是:能少工作的就少工作,能休眠的就休眠!以笔者做的这个温度记录仪为例,单片机型号选择的是STC的STC8A8K64S4A12单片机,别问我为什么选择这款单片机,因为笔者别的单片机不怎么会用,而且打样时间又比较急,所以只能在自己熟悉的单片机中,选择满足要求的,价格又比较低的,功耗又是最低的来做了。整个项目中,主要就是RTC时钟模块、NTC测温模块、按键操作模块、串口通信模块、2.4G无线模块、OLED显示模块、无线充电模块等几个部分。硬件部分,已经尽可能的将功耗降到最低了,但是发现,不管怎么操作,STC单片机正常工作的时候,电流还是有4-5mA,加上OLED显示的话,也有2-3mA,2.4G模块工作的时候电流更大,有30-40mA,这样可真算不上低功耗啊,只能从软件上来想办法了!
首先,当然要将这个最大功耗的2.4G无线模块的功耗解决。无他,最省事的让他不工作的时候去睡觉了。根据这个模块的使用手册,只需将模块的CS引脚拉高,该模块就可以去睡大觉了。果然,这个无线模块睡觉之后,整个板子的工作电流瞬间降到了10mA以内了!
接下来,就要考虑OLED的问题了,虽然说,2-3mA的电流也不算很高,但是,那也是功耗啊,几天下来也必将是一笔不小的开销。当然,当时选择OLED而并非笔段式LCD的原因也很简单,OLED的界面可以随意做呀,而且也比较好看,而笔段式LCD界面就只能固定死了,后面要修改的也比较麻烦。好吧,既然选择了,也就不说那么多理由了,只能想办法降功耗了。也没有特别好的办法,OLED的功耗也只能让他不需要显示的时候去睡觉来解决了。通过软件设置一个休眠时间,然后在休眠时间到了后,然OLED乖乖去睡觉了,需要显示的时候,再按一下按键来唤醒OLED。这样,算是勉强解决了OLED功耗的问题了吧。
接下来,整个板子的功耗也就差不多在5mA左右了,再加上前面所说的AD采样电路部分降低了一些功耗,剩下的主要就是MCU的功耗了。仔细翻阅了一下STC的手册,得到了以下信息:
由此可见,MCU的功耗最低可以降到0.1uA以下!这样的话,整个电路的功耗,基本可以做到1mA以下基本没什么问题了。但是问题来了:在STOP模式下,此时的CPU和全部的外设都是停止工作的,这岂不是扯蛋么?全部停止工作了,OLED显示怎么刷新?NTC温度怎么获取?RTC时钟怎么读取?……一系列的问题来了!可能还是经验少,想破脑袋也没想到好的办法,无奈之下,只能求助了,庆幸的是,没过多久,得到了一名网友的帮助,给我指点了一个比较好的思路:即,通过工作和休眠的时间比,来控制功耗。简单来说就是,比如,设定1秒时间为参照,比如MCU完成一次一系列操作需要100ms,那么,就让MCU工作完后,在剩下的900ms里去睡大觉,然后1秒时间到了,又把它喊起来继续工作……如此循环。这样一来,MCU的功耗便大大降低了!
在实现上述功能中,用到了STC单片机的掉电唤醒定时器。关于这个定时器的使用其实也很简单,介绍什么的就不多说了,手册上写的很清楚,笔者就简单介绍一下如何使用这个定时器。根据手册,掉电唤醒定时器的定时时间如下计算:
那么,我们需要定时1秒左右的话,只需要将该定时器的计数次数设置在1999左右即可。于是,便有了下面的操作:
就这样几句代码,MCU便可正常进入STOP模式,然后待掉电唤醒时间到,便又回到了正常工作模式。然后,我们只需要在while循环中,修改一下代码,便可实现我们前面提到的功能。由于笔者项目中的功能比较复杂,下面就以一个简单的例子来介绍一下吧。相信学单片机的小伙伴们对电灯程序再熟悉不过了吧,那么笔者就以最简单的点灯程序为例吧:
很显然,大家看惯了各种延时点灯程序,似乎很少看到这样的一种点灯程序了吧?会不会有一种一脸懵逼的感觉?当时,毫无疑问,这确实也是一种点灯的手段。程序中,P30是用来控制LED的亮与灭,硬件电路就不用说了,相信大家猜都猜到了。上述代码实现的功能就是,让LED亮1秒钟,然后再灭一秒,以此循环。
实际上,MCU工作时只分别执行了一条语句,即:P30 = 1;和P30 = 0;然后就进入了STOP模式,假设执行语句的时间是1us,掉电唤醒定时器的时间是1秒,由此可见,MCU几乎99.9%的时间都在睡大觉,自然功耗就大大降低了(此处忽略LED的功耗,只针对MCU功耗而言)。
好了,关于低功耗设计的思路就简单介绍到这了,由于笔者能力有限,暂时未想到更好的办法来降低功耗,更多的发挥空间就留个读者了。