使用GSM调制解调器发送英文短信(D-Link DWM-156)

我正在使用AT命令在C#.Net中开发GSM调制解调器(D-Link DWM-156)的应用程序。 发送英文短信时遇到问题。 我试着发送“你好”,但是我在手机里收到□□□□或者……你好。

serialPort1.DataBits = 8; serialPort1.Parity = Parity.None; serialPort1.StopBits = StopBits.One; serialPort1.BaudRate = 9600; serialPort1.DtrEnable = true; serialPort1.RtsEnable = true; serialPort1.DiscardInBuffer(); serialPort1.DiscardOutBuffer(); serialPort1.WriteLine("AT\r"); Thread.Sleep(2000); serialPort1.WriteLine("AT+CMGF=1\r"); Thread.Sleep(1000); serialPort1.WriteLine("AT+CMGS=\"09390149196\"\r") Thread.Sleep(2000); serialPort1.WriteLine("hello" + "\x1A"); Thread.Sleep(1000); 

几个修复(可能更多,但我没有看到完整的代码)。

  • 不要使用WriteLine()而是使用Write()因为\r (单独)是命令行和结果代码终止符。
  • SerialPort.WriteLine()默认写入usASCII编码的字符串,但您的GSM调制解调器需要使用AT命令编码的字符串编码。 将SerialPort.Encoding属性设置为特定编码并发送CSCS命令。 您可以通过CSCS=? 询问支持的编码CSCS=? AT命令。 即使默认GSM应该适用,我也要避免隐含地依赖于此。
  • 您不需要在每个命令之后等待,但您必须等待调制解调器应答(检查OKERROR字符串)。

来自docs :

命令行由三个元素组成:前缀,正文和终止字符。 命令行前缀由字符“AT”或“at”组成[…]终止字符可以由用户选项(参数S3)选择,默认值为CR。

在伪代码中:

 void SendCommand(string command) { serialPort.Write(command + "\r"); // Do not put here an arbitrary wait, check modem's response // Reading from serial port (use timeout). CheckResponse(); } serialPort.DataBits = 8; serialPort.Parity = Parity.None; serialPort.StopBits = StopBits.One; serialPort.BaudRate = 9600; serialPort.DtrEnable = true; serialPort.RtsEnable = true; serialPort.Encoding = Encoding.GetEncoding("iso-8859-1"); serialPort.DiscardInBuffer(); serialPort.DiscardOutBuffer(); SendCommand("AT"); // "Ping" SendCommand("AT+CMGF=1"); // Message format SendCommand("AT+CSCS=\"PCCP437\""); // Character set SendCommand("AT+CMGS=\"123456\"") // Phone number SendCommand("hello" + "\x1A"); // Message 

要检查响应(绝对避免任意等待!)你可以从这样的事情开始(原始的未经测试的适应性,所以你可能需要一些调试,请参阅这篇文章 ):

 AutoResetEvent _receive; string ReadResponse(int timeout) { string response = string.Empty; while (true) { if (_receive.WaitOne(timeout, false)) { response += _port.ReadExisting(); } else { if (response.Length > 0) throw new InvalidOperationException("Incomplete response."); else throw new InvalidOperationException("No response."); } // Pretty raw implementation, I'm not even sure it covers // all cases, a better parsing would be appreciated here. // Also note I am assuming verbose V1 output with both \r and \n. if (response.EndsWith("\r\nOK\r\n")) break; if (response.EndsWith("\r\n> ")) break; if (response.EndsWith("\r\nERROR\r\n")) break; } return response; } 

在发送命令之前添加_receive.Reset() ,当然还要将OnPortDataReceived添加为SerialPort.DataReceived事件的处理程序:

 void OnPortDataReceived(object sender, SerialDataReceivedEventArgs e) { if (e.EventType == SerialData.Chars) _receive.Set(); } 

如果您遇到麻烦(但可以连接),可以用\n替换\r \n 。 某些调制解调器不正确 (假设尚未映射到使用S3参数的13以外的任何其他内容)默认情况下使用此字符作为命令行终止符(即使它仅在V1详细输出中存在于输出中)。 更改代码或发送适当的S3