尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

低功耗PIC整机待机电流优化:用内部Flash替代外部EEPROM的工程实践

低功耗PIC整机待机电流优化:用内部Flash替代外部EEPROM的工程实践 做电池供电的设备最头疼的往往不是MCU选型本身而是整套系统的待机电流怎么都压不下去。我去年做温湿度记录仪时就踩过这个坑主控选的是Microchip的低功耗PIC单片机数据手册上休眠电流写着几百nA结果整机测下来差了二十多倍。排查到最后问题竟然出在一颗外部I2C EEPROM上。后来我直接把外部存储去掉改用PIC内部Flash做数据记录整机待机电流降了一个量级续航预期也从两年出头拉到了接近电池自放电极限。这篇文章就把低功耗PIC的功耗底细、内部Flash替代外部存储器的可行性判断以及落地过程中需要注意的工程细节一次性讲清楚给正在做类似项目的朋友一个参考。1. 低功耗PIC的功耗底子nA级数据背后的真实条件1.1 XLP系列到底强在哪数据手册没告诉你的前提Microchip的XLPeXtreme Low Power系列在低功耗MCU圈子里口碑一直不错。以我常用的PIC16F18446为例数据手册上给的典型值是Sleep模式功耗约450nA 3.0V开启看门狗后约700nA开启RTC后约850nA。这几组数字看着差别不大但放在CR2032纽扣电池的场景里每一百纳安都对应着实打实的续航差异。不过这里有个新手特别容易误解的地方数据手册上的nA数值是在特定测试条件下的典型值不是所有情况下的保证值。Microchip的测试条件通常是芯片仅保持最小系统、所有外设关闭、IO引脚配置为数字输出低电平或者高阻输入电源纹波也控制得很干净。实际项目里引脚上挂的电阻、外部器件的漏电、甚至PCB板面的污染都会叠加额外电流整机待机电流比MCU标称值高一个数量级是常态。我见过不少项目在选型阶段只盯着MCU的休眠电流板子回来一测发现连I2C上拉电阻都能吃掉好几微安。所以选低功耗MCU的时候不能只看芯片本身得站在整机功耗的角度评估整个外围电路。1.2 Sleep、Idle、Doze三种模式的选择逻辑PIC的低功耗模式不止一种至少要把Sleep、Idle、Doze这三者的差异搞清楚才能选对。SleepCPU停、主时钟停、外设时钟基本全停只保留唤醒源WDT、RTCC、外部中断、引脚变化中断等工作。这是电流最低的模式也是绝大多数低功耗项目的首选。IdleCPU停但外设继续跑。适合那种外设需要持续工作、但CPU可以歇着的场景比如串口数据接收、定时器捕捉。DozeCPU降低频率运行外设保持全速。适合需要周期性做点轻量处理但又不想频繁进出Sleep的场景。我当时的温湿度记录仪工作节奏是10秒采集一次每分钟存一条记录。这种场景下Sleep WDT定时唤醒就是最简单的组合每次唤醒做完采集、写入、再回Sleep整个活跃窗口只有几毫秒。如果改用Idle或者Doze反而会因为外设时钟继续运行而拉高平均电流。1.3 电源电压和时钟频率对功耗的影响除了休眠模式还有两个变量对PIC功耗影响很大一个是电压一个是时钟频率。电流消耗和供电电压基本呈线性关系同样是运行状态3.6V下跑和2.0V下跑电流可以差出接近一半。所以电池供电项目能降压就降压用一颗LDO把电压稳到2.0V到2.5V区间比直接怼3.3V划算得多。时钟频率的影响更直观。PIC内部有LFINTOSC典型31kHz和HFINTOSC最高32MHz级别。跑31kHz和跑32MHz运行电流差了不止两个数量级。很多低功耗项目的做法是系统平时用31kHz时钟跑主循环只有需要做数据处理或者通信的时候才临时切换到高速时钟。这一套玩熟练了整机平均电流能省下两到三个数量级。2. 内部Flash当数据存储用可行性、收益和边界2.1 擦写寿命和数据保持时间到底够不够要把MCU内部Flash用作数据存储硬件工程师第一个问题肯定是寿命。PIC的Flash在数据手册里给出的典型擦写次数是10万次数据保持时间至少40年。这个数据对大多数数据记录场景是够用的但需要算清楚账。我简单算一下。如果设备每5分钟写一次Flash一天288次一年105120次照这个频率擦写同一行一年就逼近寿命上限。但如果我们每10分钟写一次一天144次一年52560次同样只擦写同一行能撑接近两年。如果把数据分散到多行、配合磨损均衡那寿命就是区块总数乘以单块寿命量级完全不一样。所以结论是内部Flash的寿命不是瓶颈用法才是瓶颈。2.2 替代外部EEPROM和SPI Flash的收益清单把外部存储去掉省下来的不只是芯片本身那几毛钱。外部I2C EEPROM在读写时需要总线通信I2C速度通常400kHz读写一页数据加通信开销要几毫秒这些时间MCU必须保持运行状态电流在mA级别。而访问内部Flash是寄存器操作没有总线握手时间。I2C/SPI总线上的上拉电阻一直在耗电尤其在上拉电阻接到低电压域的时候。休眠状态下这些电阻的漏电全部算到整机待机电流里。外部存储芯片有自己的待机电流虽然标称通常很低但不同批次、不同温度下差异很大。少一颗芯片就少一组去耦电容、少几根走线PCB面积和布线复杂度都降了信号完整性问题也少一个。BOM成本里带扩展温度等级的存储芯片价格并不便宜加上贴片费用省下的钱足够在MCU上多买几KB Flash了。2.3 自读写机制和仿真EEPROM思路PIC的Flash支持自读写也就是程序运行过程中可以对Flash进行编程和擦除。这给了我们一个思路把Flash的高地址区域划出来当EEPROM一样用。具体做的时候有几点要知道。Flash的最小编程单位通常是字比如14位或16位不同型号不一样最小擦除单位是行比如一行32字节或64字节。擦除操作会把整行清成全1编程操作只能把1改成0。所以如果只是想修改某一行里的几个字节需要先读出来、改掉、擦掉整行、再写回去。这个读-改-擦-写流程比较费时间所以工程上更常见的做法是新增一条记录时直接在当前行找下一个空闲位置写入不重复擦写旧区域。只有当整个数据区都写满了才做一次整体擦除重新开始下一轮。这就是最简单的仿真EEPROM方案配合磨损均衡可以把有效擦写次数放大很多倍。3. 从外部EEPROM迁移到内部Flash的改造实录3.1 原始方案的整机功耗诊断先还原一下我当时的项目状态。电路板上有一颗PIC16F18446占空比大概是这样10秒一周期唤醒后读温湿度传感器I2C、存一条记录到外部24LC64、再进Sleep单次活跃时间约20毫秒。整机待机电流实测8μA左右比MCU手册上的450nA高了将近18倍。我用排除法逐个查先把MCU进入Sleep断开外部EEPROM的供电待机电流降到了2μA。再把I2C上拉电阻摘掉又降了约1.2μA。剩下的几百nA来自电源芯片静态电流、传感器待机电流等。也就是说光外部EEPROM供电、上拉电阻、以及读写时的额外活跃时间就吃掉了将近6μA。对于一颗2032电池来说6μA意味着一年就要耗掉约52mAh占电池容量的四分之一左右。这个损耗太不值了。3.2 内部Flash存储区的划分和记录格式设计把外部EEPROM去掉之后我在PIC16F18446的Flash里划出了最后4KB作为数据记录区。16F18446的Flash容量有多个档位我这颗是32KB划掉4KB后剩28KB给程序完全够用。记录格式是这么定的每条记录8字节前4字节放时间戳中间2字节放温度最后2字节放湿度。每条记录的第一个字节最高位当作有效标志——写入时该位置0表示有效如果需要删除比如数据上传成功后清理就把该位置1这样不需要擦除Flash就能实现软删除。磨损均衡用了个简单办法整个4KB数据区再分成8个块每块512字节。写入时按行顺序填当前块写满后切到下一块。所有块都写满了就整体擦除一遍重新从第一个块开始。这样有效擦写次数大约是单块寿命乘以块数4KB区域的行数大约有128行配合10万次行擦写寿命总擦写预算至少千万次级别足够设备用很多年。3.3 改版后的实测数据变化改造完成之后的整机测试结果整机待机电流从8μA降到了500nA以内绝大多数电流来自LDO静态功耗和传感器待机。单次唤醒工作时间从20ms缩短到3ms左右因为省掉了与外部EEPROM的I2C通信过程。单条记录写入时间从约5ms降到约1ms最快的瓶颈变成了Flash编程本身。BOM减少了一颗EEPROM、两个上拉电阻、一个去耦电容。PCB面积释放出约4mm x 3mm的空间这对于小型化很有意义。电池续航重新估算了一下。原方案整机平均电流约10μA2032电池可用寿命约2年出头改完后平均电流约1.5μA理论可用寿命达到15年以上实际被电池自放电限制一年半到两年左右还得换电池但这颗电池的利用率已经高多了。4. 工程化落地中的几个实际坑磨损、掉电和测量4.1 磨损均衡的最小实现思路很多项目在不用外部EEPROM以后最容易翻车的就是Flash磨损问题。这里给一个最小可用的磨损均衡设计思路直接拿去改就能用。用一组RAM变量维护当前写入状态currentBlock当前块号、currentOffset当前块内偏移、totalBlocks总块数。每次写数据时在currentOffset位置写入然后递增。如果currentOffset超出块容量就切到下一个块如果currentBlock已经到最后一个块则整片擦除回到初始状态。这里面有一个取舍整体擦除会丢掉所有旧数据所以只适合存丢了也无所谓的历史记录。如果数据必须长期保留就得用双备份或者移动指针的复杂方案。我的经验是先从最简单方案跑起来确认功能没问题再决定要不要增加可靠性设计。4.2 掉电保护和数据完整性电池设备最怕的就是写Flash写到一半掉电。Flash擦除如果中断可能会出现整行数据变成不可读状态。要避免这种情况建议从三个层面下手。第一开启PIC的BOR掉电复位功能。电源电压跌到阈值以下时BOR会强制复位MCU防止在电压不稳的状态下执行Flash写操作。很多项目觉得BOR可有可无但在电池供电产品里真的建议开着。第二写入顺序上做一个简单的双备份。数据区维护主记录和备用记录两个副本写入时先写备用记录确认成功后再更新主记录。上电启动时比较两个副本的序列号取最新的一份。这个方案等于用一倍存储空间换数据可靠性。第三写Flash之前先把关键状态保存到RAM并且只在一个明确的、短的窗口内做Flash操作。窗口越短掉电落在窗口内的概率越小。4.3 功耗测量和开发板陷阱最后聊聊功耗测量。低功耗项目里测量手段错了结论就全错了。万用表串联测电流这个方法在休眠态和运行态电流差距很大的场景下不太靠谱。万用表显示的是采样时间内的平均值很可能把休眠态的低电流和运行态的高电流平均成一个中间值让人误判。想看真实波形建议用电流探头加示波器或者用支持长时间日志记录的精密电流监测仪。另外提醒一个很容易踩的坑开发板上的电源指示灯、调试器芯片、USB转串口芯片在休眠时全都在耗电。拿开发板直接测整机功耗数字永远降不下来。我一般都会做一块最小系统板只焊MCU和必要的阻容元件这样才能得到可信的底噪电流。如果还想再进一步降低功耗可以考虑把测量环境放到恒温箱里做高低温电流测试因为Flash的编程电流和漏电都会随温度变化。工业级产品把这个走一遍省得现场出问题再回来排查。关于Flash容量规划我还有一条实操建议选型阶段就把数据存储需求量化。每条记录多少字节、最多存多少条、要不要备份、Bootloader是不是也要动Flash把这些数字加起来再乘以2到3倍的余量才是真正需要选的Flash容量。别等代码写得差不多才想起来存储区不够那时候再换MCU就麻烦了。我自己在实际项目里还发现一个规律每次写完Flash最好加一个校验步骤读回数据做比对。Flash编程偶尔会因为电压波动产生翻转错误多一个校验心里踏实很多。尤其在对数据可靠性要求高的场景里这个步骤不能省。这套低功耗PIC加内部Flash的方案我用在好几个电池设备上了整体感受是把整机功耗的账算清楚、把Flash的寿命管理好低功耗和存储两个问题就都解决了。如果你也在做类似的产品建议从最小系统开始验证先跑通一条存储记录再逐步加上磨损均衡和掉电保护稳扎稳打。
返回列表