4G模块AT指令实战:从Text到PDU模式发送中文短信的避坑指南

📅 2026/7/15 4:01:47
4G模块AT指令实战:从Text到PDU模式发送中文短信的避坑指南
1. 4G模块短信发送模式选择Text vs PDU第一次用4G模块发中文短信时我踩了个大坑用Text模式发了条设备告警温度过高结果对方收到的是乱码。后来才发现Text模式对中文支持就是个薛定谔的猫——理论上可以实际全靠运气。经过多次实测总结出两条铁律Text模式适合纯英文/数字场景指令简单直观。比如发个验证码Your code: 123456用Text模式三行AT指令搞定ATCMGF1 ATCMGS13800138000 Hello World\x1APDU模式才是中文短信的真命天子。虽然编码过程像玩魔方但兼容性绝对靠谱。同样的中文内容PDU模式需要经过短信中心号编码奇偶位交换手机号编码补F奇偶位交换中文转Unicode比如测试→6D4B8BD5组合成PDU串实测对比数据指标Text模式PDU模式中文支持部分运营商不支持100%兼容指令复杂度★☆☆☆☆ (简单)★★★★☆ (复杂)数据量原始文本编码后体积增加30%典型响应时间2-3秒3-5秒特别提醒有些模块比如SIMCOM的SIM7600在Text模式下发中文会偷偷转成PDU格式发送。这种伪Text模式反而容易导致混乱建议统一用PDU模式。2. PDU模式编码避坑实战2.1 短信中心号处理90%新手的第一道坎去年给某智能水表项目调试时连续20条短信发送失败最后发现是短信中心号少了个F。PDU编码的第一个拦路虎就是短信中心号处理分三步走获取本地号码用ATCSCA?查询注意问号别漏比如返回8613800100500奇偶位交换# Python示例代码 sca 8613800100500 sca sca[1:] F # 去掉号补F → 8613800100500F pdu_sca .join([sca[i1]sca[i] for i in range(0,len(sca),2)]) # 得到 683108100005F0添加长度字节长度原始号码字符数去掉号后十六进制表示。上例中8613800100500是13位补F后14位即0x0E→0E常见错误漏掉国家代码86开头忘记补F凑偶数长度计算错误应该用交换前的字符数2.2 手机号编码小心国际标志位给8613812345678发短信时如果直接编码会提示invalid number。PDU格式要求类型字节必须为91国际号码号码要去掉号并补F# 原始号码8613812345678 1. 去 → 8613812345678 2. 补F → 8613812345678F 3. 奇偶交换 → 683118325476F8长度字节是号码数字位数不含十六进制。上例11位→0x0B2.3 中文编码Unicode的坑温度告警四个字用在线工具转Unicode得到6E29→5EA6→544A→8B66但直接发送会乱码。必须注意字节序问题模块要求大端序高位在前而某些工具输出小端序长度计算ATCMGS参数是字节数中文长度字符数×2DCS设置必须为08UCS2编码推荐用Python标准库编码content 温度告警.encode(utf-16be).hex().upper() # 得到 6E295EA6544A8B663. AT指令序列优化方案3.1 完整PDU发送流程以发送设备重启到13800138000为例初始化模块ATCMGF0 # 切换PDU模式 ATCSCSUCS2 # 设置Unicode编码发送PDU数据ATCMGS19 # PDU数据长度(字节) 0011000B913168108001F0000800048BBEE7D6B53D\x1A其中PDU串组成00 # 使用预设短信中心 11 # 报文类型 00 # 消息参考 0B # 目标号码长度(11位) 91 # 国际号码 3168108001F0 # 编码后的手机号 00 # PID 08 # DCS(UCS2) 0004 # 有效期 04 # 用户数据长度(4字符×2) 8BBEE7D6B53D # 设备重启的Unicode3.2 错误处理机制某次现场调试发现短信成功率只有60%后来加入重试机制后提升到99%。关键策略超时检测每条指令设置3秒超时状态机控制graph TD A[发送ATCMGS] --|成功| B[等待提示符] B -- C[发送PDU数据] C --|5秒内无响应| D[记录错误日志] C --|收到CMGS| E[发送成功]典型错误码处理CME ERROR 10SIM卡未就绪→检查ATCPIN?CME ERROR 302存储满→发送ATCMGD1,4清空4. 中文乱码问题排查清单遇到乱码时按照这个顺序检查编码一致性验证确认所有环节统一使用UCS2用ATCSCS?查询当前编码设置PDU结构诊断# 示例错误PDU 0891683108100005F011000B913168108001F0000800048BBEE7D6B53D # 分段验证 - 0891...F0 # 短信中心部分 - 11000B91...F0 # 目标地址部分 - 000804...B53D # 用户数据部分模块兼容性测试发现某些模块如EC20需要额外配置ATQCMGS1 # 启用长短信支持实测案例某项目用SIM7600发中文必须添加ATCSMP17,167,0,8才能正常显示。5. 性能优化技巧预编码缓存对于固定内容如告警模板提前计算PDU编码批量发送策略// 伪代码示例 for(int i0; i3; i){ if(send_pdu(pdu_data)) break; delay(1000 * (i1)); // 指数退避 }内存管理发送长短信时建议分片# 第一片 ATCMGS82 0051000B...000A06C4E09B44... # 第二片 ATCMGS56 0051000B...000B4F60D898DE...最后分享一个真实踩坑记录某次发送设备IDA-102始终失败后来发现短横线-在GSM 7bit编码表中不存在。解决方案是强制使用UCS2编码或者替换为全角。