You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 20:15:02