C#用AT指令发送含UDH的UCS2编码长短信出现乱码如何解决
问题根因
你当前的实现把UDH的十六进制表示字符串直接作为文本内容拼接,相当于把0、5、0、0这类字符当成了短信正文的一部分编码发送,而非把UDH作为二进制头嵌入用户数据段。再加上海未开启UDH标识位,接收端直接将UDH内容当作文本解码,自然出现乱码。
正确实现步骤
1. 优先切换到PDU模式发送长短信
TEXT模式(AT+CMGF=1)对带UDH的长短信兼容性极差,不同厂商模组的实现规则不统一,PDU模式是发送长短信的标准实现方式,不会有兼容性问题。如果坚持使用TEXT模式,可按后续步骤修改。
2. 开启UDH标识位
将AT+CSMP的第一个参数从17改为49(十进制49对应二进制00110001,第6位置1表示存在用户数据头),指令改为:
serialPort.Write("AT+CSMP=49,167,0,8" + Char.ConvertFromUtf32(13));
3. 正确拼接UDH和内容
UDH是二进制字节序列,不能直接把十六进制字符串拼在前面,需要先把UDH的十六进制串转为字节数组,再和短信内容转成的UCS2字节数组合并,最后把合并后的完整字节数组转成十六进制字符串发送:
// 1. 构造UDH字节数组 byte[] udh = new byte[] { 0x05, 0x00, 0x03, 0xCC, 0x02, 0x01 }; // 2. 构造内容UCS2字节数组(UCS2为大端双字节编码) byte[] content = Encoding.BigEndianUnicode.GetBytes("dddd"); // 3. 可选:如果UDH长度为奇数,需补1个0x00字节保证后续UCS2双字节对齐 byte[] padding = udh.Length % 2 == 1 ? new byte[] { 0x00 } : new byte[0]; // 4. 合并所有字节 byte[] fullUserData = new byte[udh.Length + padding.Length + content.Length]; Buffer.BlockCopy(udh, 0, fullUserData, 0, udh.Length); Buffer.BlockCopy(padding, 0, fullUserData, udh.Length, padding.Length); Buffer.BlockCopy(content, 0, fullUserData, udh.Length + padding.Length, content.Length); // 5. 把完整字节数组转成十六进制字符串 string messageSmsEncoded1 = BitConverter.ToString(fullUserData).Replace("-", "");
4. 其余AT指令逻辑保持不变,替换原来的messageSmsEncoded1构造逻辑即可。
注意事项
- 同一长短信的所有分片,UDH中的参考标识(示例中的
0xCC)必须保持一致 - 分片序号从1开始计数,不要填0
- 单条分片的总长度(UDH+填充+内容)不要超过140字节,超过需要拆分为更多分片
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

