我正在使用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);
答案 0 :(得分:1)
很少有修复(可能更多,但我不会看到完整代码)。
WriteLine()
,而是使用Write()
,因为\r
(单独)是命令行和结果代码终止符。SerialPort.WriteLine()
默认写入usASCII编码的字符串,但您的GSM调制解调器需要使用AT命令编码的字符串编码。将SerialPort.Encoding
属性设置为特定编码并发送CSCS
命令。您可以使用CSCS=?
AT命令询问支持的编码。即使默认GSM应该适用,我也要避免隐含地依赖它。OK
或ERROR
字符串)。来自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
要检查响应(绝对避免任意等待!),您可以从这样的事情开始(原始未经测试的适应性,因此您可能需要一些调试,另请参阅this post):
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();
}
如果您遇到问题(但可以连接),可以将\r
替换为\n
。某些调制解调器错误(假设<CR>
未使用13
参数映射到S3
以外的任何其他内容)默认情况下将此字符用作命令行终止符(即使它应该只出现在V1
详细输出的输出中。您可以更改代码或发送相应的S3
。