问题描述
我开发GSM调制解调器(D-Link的DWM-156)在C#.NET中使用AT命令的应用程序。我在发送英文短消息的问题。
我尝试发送你好,但是我收到□□□□在我的手机或... exept打招呼。
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(你好+\x1A);
Thread.sleep代码(1000);
一些修正(也许更多,但我没有看到全码)。
- 请不要使用
的WriteLine()
,但写()
,因为\r
(单独)是命令行和结果代码终止符。 -
SerialPort.WriteLine()
在默认情况下写一个USASCII编码字符串,但你的GSM调制解调器期待与AT指令指定的编码字符串。设置SerialPort.Encoding
属性设置为特定的编码并发送CSCS
命令。你可以的询问的有CSCS =?
支持的编码AT命令。即使默认的GSM应适用我会避免隐含靠这个。 - 您不需要在每个命令后等待,但你必须等待调制解调器的答案(检查
确定
或错误
字符串)。
通过:
在伪代码:
无效SendCommand(字符串命令){
serialPort.Write(命令+\r);
//不要把这里任意的等待,检查调制解调器的应答
//从串口(使用超时)阅读。
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); //平
SendCommand(AT + CMGF = 1); //报文格式
SendCommand(AT + CSCS = \PCCP437\); //字符集
SendCommand(AT + CMGS = \123456\)//电话号码
SendCommand(你好+\x1A); //消息
要检查响应(绝对避免任意等待!),你可以像这样启动(未经检验的原料适应性,所以你可能需要一些调试,也见):
的AutoResetEvent _receive;
串ReadResponse(INT超时)
{
串响应=的String.Empty;
,而(真)
{
如果(_receive.WaitOne(超时,FALSE))
{
响应+ = _port.ReadExisting();
}
,否则
{
如果(response.Length大于0)
抛出新的InvalidOperationException异常(未完成的回应。);
,否则
抛出新的InvalidOperationException异常(不回应。);
}
//漂亮原始的实现,我甚至不能确定它涵盖
//所有的情况下,更好的分析会在这里感激。
//另请注意,我假定既\r和\\\
详细V1输出。
如果(response.EndsWith(\r\\\
OK\r\\\
))
中断;
如果(response.EndsWith(\r\\\
>))
中断;
如果(response.EndsWith(\r\\\
ERROR\r\\\
))
中断;
}
返回响应;
}
添加 _receive.Reset()
您发送的命令,当然还加入之前 OnPortDataReceived
的处理程序 SerialPort.DataReceived
事件:
无效OnPortDataReceived(对象发件人,
SerialDataReceivedEventArgs E)
{
如果(e.EventType == SerialData.Chars)
_receive.Set();
}
如果你有一些麻烦(但您可以连接),你可以替换 \r
与 \\\
。有些调制解调器的错误的(假设
< CR>
尚未映射到任何东西比 13
使用 S3
参数)在默认情况下使用该字符作为命令行结束(即使它应该只对 V1 详细输出)。要么改变你的代码,或发送相应的
S3
。
I am developing an application for GSM Modems (D-Link DWM-156) in C#.Net using AT commands. I have a problem sending English SMS. I try to send "hello", But I receive □□□□ in my phone or ...exept hello.
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);
解决方案 Few fixes (maybe more but I don't see full-code).
- Do not use
WriteLine()
but Write()
because for \r
(alone) is the command line and result code terminator character. SerialPort.WriteLine()
by default writes a usASCII encoded string but your GSM modem expect strings encoded as specified with an AT command. Set SerialPort.Encoding
property to a specific encoding and send CSCS
command. You can ask supported encodings with CSCS=?
AT command. Even if default GSM should apply I'd avoid to rely implicitly on this.- You do not need to wait after each command but you have to wait for modem answer (checking for
OK
or ERROR
strings).
From docs:
In pseudo-code:
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
To check response (absolutely avoid arbitrary waits!) you can start with something like this (raw untested adaption so you may need some debugging, see also 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;
}
Adding _receive.Reset()
just before you send your command and of course also adding OnPortDataReceived
as handler for SerialPort.DataReceived
event:
void OnPortDataReceived(object sender,
SerialDataReceivedEventArgs e)
{
if (e.EventType == SerialData.Chars)
_receive.Set();
}
If you have some trouble (but you can connect) you may replace \r
with \n
. Some modems incorrectly (assuming <CR>
has not been mapped to anything else than 13
using S3
parameter) use this character as command line terminator by default (even if it should be present in output only for V1
verbose output). Either change your code or send appropriate S3
.
这篇关于发送英文短消息与GSM调制解调器(D-Link的DWM-156)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!