做电池供电的物联网设备最怕的不是模组发数据那一下的电流尖峰而是既不干活又不睡觉时慢慢漏掉的待机电流。我手头这个项目是 STM32L431 加移远 EC200S走 MQTT 上报温湿度和定位业务又要求平台随时能下发命令所以模组没法用 PSM 那种深层睡眠只能让它在空闲态 DRX 下待机。理想情况是整机休眠电流做到 6mA 附近结果第一次实测直接在电池端看到 13mA续航硬生生砍了一半。一开始我以为只是 AT 指令没配好结果翻完手册、改完配置发现这个 13mA 背后藏着三个特别典型的坑DTR 电平没控制、URC 和 MQTT 保活把模组反复唤醒、还有模组本身之外的整板漏电。这篇就把我排查的过程、最终落地的 AT 指令流程和实测数据完整记录下来给正在做 STM32移远 4G 模块连接 MQTT 这类电池供电项目的朋友做个参考。1. 先算功耗账再动手查电流1.1 13mA 和 6mA 差了多少续航别小看这几毫安的差距电池供电产品算账非常直观。13mA 乘以一天 24 小时就是每天消耗 312mAh。一块 4000mAh 电池按 80% 可放容量算只能撑 10 天出头如果把电流压到 6mA每天耗电 144mAh同样的电池能撑到 22 天左右续航直接翻倍。模组偶尔发一次数据那点电流反而不是大头。按发 100 条消息、每条持续 5 秒、平均 100mA 算一天也就 13.9mAh跟待机电流比起来微不足道。所以做低功耗蜂窝设备第一优先级永远是压待机电流压传输时间收益反而小。我在项目里给自己定的目标是整机休眠 6mA 左右。这个数字不是随手拍出来的EC200S 在空闲态 DRX 下、网络信号正常时典型电流就在 5 到 8mA 之间。如果连续测出来是 13mA说明模组要么根本没睡要么有外围电路在额外偷电。1.2 测量方法摆不正后面全白干功耗排查第一步其实是把“量得多准”这个问题解决掉。我吃过大亏拿万用表 10A 档串进去测表显 0.01 到 0.02 波动根本分不清 6mA 和 13mA 的差别。后来换成台式电源的电流回读功能或者用精密采样电阻加示波器看波形才算靠谱。测量位置也比想象中关键。我习惯在电池接口处串表测整机电流同时预留一个单独的模组供电跳线帽可以只量模组 VCC 上的电流用来区分是模组本身耗电还是整板外围耗电。另外有一点必须提醒EC200S 这类模组从串口空闲到真正睡过去往往需要几十秒千万别发完 AT 指令就立刻读数。我自己的做法是让设备跑完一轮完整上报确认串口没有流量后再等 90 秒取平均值。这样测出来的数字才有参考价值。2. 坑一DTR 没拉低模组根本不进休眠2.1 DTR 引脚到底是怎么控制休眠的移远 EC21、EC200S 这一类模组UART 硬件休眠基本是靠 DTR 引脚来协商的。DTR 是高电平模组认为主机还醒着始终保留串口接收能力自然不会往低功耗状态走DTR 拉低之后模组才允许自己在一段时间串口空闲后进入休眠。问题往往出在开发板上。很多评估板和最小系统板把 DTR 接到了 USB 转串口芯片上平时插着电脑跑 AT 调试没问题但设备真正脱离电脑、由单片机控制时这个引脚可能浮空或者被上拉电阻拉高模组就一直处于“随时等待主机命令”的状态。你 AT 指令配得再漂亮它也没法睡。我最初在原理图上看到 DTR 上有个 10k 上拉下意识以为是模组的使能脚高电平才正常。后来翻 EC200S 硬件设计手册才发现方向反了要想休眠必须把 DTR 拉低。这一步纠正之后休眠电流立刻从 13mA 掉到了 8mA 左右问题解决了一大半。2.2 硬件和代码侧怎么配合处理正确的接法是把模组 DTR 接到 MCU 的普通 GPIO 上单片机进入低功耗模式前把该 GPIO 输出低电平唤醒后再拉高。为了怕 MCU 复位期间引脚状态不确定我还在模组侧加了一个 100k 下拉电阻保证上电瞬间 DTR 是低电平模组不会因为引脚悬空而误判主机状态。代码上也不复杂大致逻辑是这样// 进入休眠前 HAL_GPIO_WritePin(DTR_GPIO_Port, DTR_Pin, GPIO_PIN_RESET); // 拉低允许模组睡 HAL_UART_DeInit(huart1); // 关闭串口外设 HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); // 关指示灯 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); // RTC 唤醒后 HAL_GPIO_WritePin(DTR_GPIO_Port, DTR_Pin, GPIO_PIN_SET); // 拉高叫醒模组 HAL_Delay(50); // 给模组反应时间 HAL_UART_Init(huart1); // 重新初始化串口有一点要特别留意模组睡过去之后串口 RX 引脚不再处于活跃监听状态这时候你要是直接发 AT 指令很可能石沉大海。正确的唤醒顺序是先拉高 DTR等几十毫秒再发第一条 AT 指令。千万不要省这个延时否则会出现第一次指令无响应、要发两次才成功的现象。3. 坑二URC 和 MQTT 保活在悄悄唤醒模组3.1 你以为配好了 PSM其实 URC 一直把模组叫醒URC 全称是主动上报结果码比如CEREG: 1这种网络注册状态变化、CSCON: 1信号连接建立、QUSIM: 1SIM 卡状态、socket 收到数据的QIURC等等。问题在于模组要产生任何一条 URC内部的协议栈处理器都得先醒过来。我一开始为了调试方便把所有 URC 都开着的注册状态变化报一下、信号强度变化报一下、TCP 连接断了也要报一下。这在调试阶段没什么但设备长期运行时网络环境稍微有点风吹草动模组就频繁被内部事件唤醒睡眠时间被切得稀碎平均电流自然下不来。处理办法是把量产固件里不需要的 URC 全部关掉。常用的几条命令是ATCEREG0 ; 关闭注册状态 URC ATCSCON0 ; 关闭信号连接状态 URC ATQURCCFGurcport,none ; 关闭主串口上的 URC 上报不过这里有个坑ATQURCCFG的具体用法在不同固件版本里有差异有的版本是urcport,uart1有的直接写disable。我强烈建议配置之前先查一下自己这颗模组固件对应的 AT 指令手册别照着网上的命令盲抄。CLOSED 类 socket 状态变化如果会占用 URC还要检查模组自带的 TCP/IP 协议栈里相关 URC 使能项。3.2 MQTT 长连接是隐藏的耗电大户我最初 13mA 里相当一部分其实是 MQTT 长连接贡献的。默认情况下模块里的 MQTT 客户端要按 keepalive 周期发心跳我测试阶段用的是 30 秒一次一次心跳从唤醒到发送完再睡过去大概 2 到 3 秒期间电流跑到 60 到 100mA。平均下来光心跳一项就吃掉好几毫安加上 DTR 没处理时模组始终不睡整体电流就冲到 13mA 了。所以做低功耗蜂窝项目必须想清楚一个问题平台能不能接受设备断线重连如果能接受那最省电的方案是上报完数据就主动关闭 TCP/MQTT 连接让模组彻底进入空闲状态下一次上报再重新连。如果不能接受那至少把 keepalive 从 30 秒拉到 300 秒以上同时配合 eDRX 降低监听寻呼的频率。我实际跑下来的感受是长连接和低功耗从来都是矛盾的。你让模组时刻保持 socket 在线它就必然要周期性醒来维护连接你允许它断线功耗才能回到散步级别。产品经理如果跟你说“要能秒级下发又要一个季度不换电池”基本是在为难硬件工程师。3.3 我的处理顺序和实测数据改动顺序我建议是先关 URC再调 keepalive最后断 socket 重连每做一步测一次电流方便定位是哪一块在耗电。我的实测记录大致是这样调整动作整机休眠电流原始状态DTR 未拉低 URC 全开 keepalive 30s13mA拉低 DTR模组允许休眠8mA关闭 CEREG/CSCON/URC 上报keepalive 改为 300s6.5mA休眠前主动断开 MQTT 连接上报时重新连接6.1mA后面这一串操作都是软件层能解决的没有改原理图整体收益却非常明显。尤其是把“上报后保持连接”改成“上报后断开连接”对功耗的改善是质的飞跃代价只是下次唤醒后多了几百毫秒的重连时间。4. 坑三整板漏电模组睡了你没睡4.1 分块测量把泄漏点揪出来当模组单独供电测下来只有 6mA 出头、整机却还是 13mA 的时候基本可以断定问题出在模组之外的外围电路。最简单的定位方法是一路一路切把 USB 转串口芯片的电源跳线拆了测一次把 SIM 卡座检测脚断开测一次把天线检测分压电阻拿掉再测一次。我这块板子上最大的一条漏电路径居然是调试用的 USB 转串口芯片。当时为了方便看日志USB 转 TTL 模块一直插在主板上CP2102 这类芯片自身静态电流就有几毫安它还顺带通过电平转换电路把模组串口引脚钳在了一个非理想电平上让模组在 DTR 拉低之后依然判断“主机在线”。拔掉这个调试模块的跳线帽整板电流直接掉了 6mA最终稳定在 6.1mA。4.2 最容易漏电的四个位置串口电平转换芯片TXS0108、MAX232 这类芯片静态电流从几百微安到几毫安不等如果只是调试需要量产板上尽量去掉或加电源控制。SIM 卡检测脚和 SIM_VDD 电路很多 SIM 卡座上的 card detect 脚带着上拉平时不插卡也在耗电这部分虽然单个不大但和模组休眠电流叠加起来就不可忽视了。电源指示灯和网络状态灯一颗 LED 加上限流电阻就是 1 到 3mA休眠时指示灯不灭的话等于白送给功耗预算。天线检测 ANT_DET 引脚有些设计在这个脚上做了分压电阻模组休眠时这部分电流会通过外部走线漏掉。排查这类问题的时候别一上来就怀疑模组。先量模组单独供电的电流再量整机电流两者差值越大外围漏电嫌疑越大。我甚至遇到过模组 VCC 上的滤波电容因为焊反导致漏电流偏大的情况所以也要顺带检查电源轨上有没有焊错、焊损坏的元件。4.3 修复之后 13mA 到 6mA 的构成拆解最终整机 6.1mA 的构成大概是模组 EC200S 在空闲态 DRX 下待机约 5.8mAMCU 休眠约 0.1mA传感器电路在断电状态下约 0.05mA其他静态漏电流约 0.15mA。这个水平对于需要随时保持模组在线的产品来说已经比较理想了。如果还想继续往下压方向就是让模组进入真正的 PSM 模式实测能到几十微安但代价是平台侧下发命令会延迟到下一个激活窗口。这属于产品形态取舍的问题不是单纯调 AT 指令能解决的。5. 完整 AT 指令流程直接抄作业5.1 配置之前的清理和确认功耗问题开始之前先把模组恢复到干净状态避免之前调试的残留配置影响判断。我每次量产配置都会走一遍这一步AT OK ATF OK ATE0 OK ATCFUN1 OKATF是恢复出厂设置ATE0关闭回显ATCFUN1确保射频部分处于正常开启状态。做完这组指令后先测一轮当前电流作为基线再往下配置。5.2 PSM 和 eDRX 的配置命令与参数计算配置 PSM 的关键是理解ATCPSMS的参数编码。命令格式是ATCPSMSmode,,,Requested_Periodic-TAU,Requested_Active-Time后面两段是 8 位二进制字符串编码规则来自 3GPP 24.008 里的 GPRS Timer高三位是单位低五位是数值。比如我希望 TAU 周期是 6 小时Active Time 是 60 秒。TAU 用单位 0111 小时加数值 6写成01100110Active Time 用单位 0011 分钟加数值 1写成00100001。这条命令就是ATCPSMS1,,,01100110,00100001 OKeDRX 可以进一步降低空闲态监听寻呼的频率我的配置是ATCEDRXS1,5,0010 OK同样提醒一句eDRX 能不能生效取决于运营商网络是否支持参数值也不是随便填的测试时要看网络侧返回的实际协商结果。5.3 怎么确认模组真的进了 PSM配置完别急着开心先验证一下。先开网络注册详细上报ATCEREG5 OK然后等模组重新附着网络查询当前状态ATCEREG?如果返回的字符串末尾跟着两段引号括起来的 Active-Time 和 Periodic-TAU 值比如CEREG: 5,4600F,1A2B3C,7,01100110,00100001说明网络已经接受了 PSM 参数。如果末尾什么都没有基本可以认为这颗网络没支持你配的 PSM 参数或者组合方式不对需要换个参数组再试。需要特别注意的是改完 PSM 配置后最好让模组重新附着一次简单粗暴的方式是ATCFUN0 ATCFUN1让它带着新参数重新注册否则可能还是沿用老的附着参数配置等于白做。5.4 落地到 STM32 项目里的时序建议AT 指令部分解决的是“模组允许睡”的问题真正让系统低功耗跑起来还需要 MCU 侧配合。完整时序大概是上报完数据、收到云平台 ACK 之后先主动断开 MQTT 连接接着关掉多余的 URC 输出然后拉低 DTR 让模组进入空闲态最后 MCU 自己进 STOP 模式。到下一次预定上报时间RTC 唤醒 MCUMCU 先拉高 DTR 叫醒模组等 50 毫秒左右再开始走 AT 指令流程。一个我踩过的小坑是MCU 的串口 RX 引脚如果配置成带上拉的输入在模组休眠期间可能会被模组串口的静态电平钳住形成微弱电流。后来我把所有接模组的 GPIO 在休眠前改成模拟输入或下拉输入电流又往下走了一点点。这类细节看着不起眼积少成多就是毫安级别的差距。6. 常见问题与排查经验速查6.1 我踩过的典型问题记录现象可能原因解决办法配了 CPSMS 但 CEREG 查询末尾没有时间参数网络侧拒绝该组 PSM 参数或不支持 PSM换一组 TAU/Active Time 参数或换运营商测试DTR 拉低后发 AT 指令没反应模组已真的休眠串口不监听先拉高 DTR延时 50 到 100ms 再发指令电流波动很大平均值飘忽不定MQTT keepalive 或 TCP 心跳持续唤醒模组拉长 keepalive 间隔或上报后断开连接USB 调试线一拔电流下降明显USB 转串口芯片和电平转换在整板耗电量产板去掉调试芯片或给调试电路加独立供电跳线显示休眠电流 6mA但整机撑不过一周可能还有传感器、指示灯等外围漏电逐路断电测电流做分块定位eDRX 配置后电流没变化网络不支持 eDRX 或终端未重新附着打开 CEREG5 确认协商结果必要时重新附着6.2 排查工具和操作顺序建议手头没有高端功耗分析仪也没关系一台带 0.1mA 分辨率回读的台式电源就够用了。要抓电流波形的话可以用示波器加低阻采样电阻或者干脆用支持电流曲线的开发工具比如 Nordic 的 PPK2 这类设备。真正重要的不是多贵的仪器而是让设备在一个真实的周期里跑完整的一轮休眠和唤醒连续观测至少几分钟的电流曲线这样周期性唤醒的规律一眼就能看出来。我的排查顺序是先量基线再关 URC再调 MQTT keepalive再断 socket再检查外围漏电最后才是动 PSM/eDRX 参数。每次只改一个变量改了立刻测一轮记录到表格里。功耗优化最忌讳一次性改一堆东西出了问题根本没法反推。6.3 一点个人经验做了这么多次低功耗调试我的体会是AT 指令只是临门一脚真正的战场在系统架构和电路设计。如果你的产品允许模组断线重连那先把架构改成短连接功耗立刻就会降下来如果一定要保持长连接那就得接受空闲 DRX 带来的几个毫安然后把外围漏电压到极致一条一条去“抠”。我后来把所有调试口都加了跳线帽量产固件里根本不去初始化 USB 转串口芯片这一个小改动比调多少条 AT 指令都管用。功耗这件事永远是整体设计的结果不是一个神奇指令能搞定的。