问题描述
我正在使用 AT 命令在 C#.Net 中为 GSM 调制解调器 (D-Link DWM-156) 开发应用程序.我在发送英文短信时遇到问题.我尝试发送你好",但我在手机中收到 □□□□ 或者...除了你好.
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
");
Thread.Sleep(2000);
serialPort1.WriteLine("AT+CMGF=1
");
Thread.Sleep(1000);
serialPort1.WriteLine("AT+CMGS="09390149196"
")
Thread.Sleep(2000);
serialPort1.WriteLine("hello" + "x1A");
Thread.Sleep(1000);
推荐答案
修复很少(可能更多,但我没有看到完整代码).
Few fixes (maybe more but I don't see full-code).
- 不要使用
WriteLine()
而是使用Write()
因为 SerialPort.WriteLine()
默认情况下会写入 usASCII 编码字符串,但您的 GSM 调制解调器需要使用 AT 命令指定的编码字符串.将SerialPort.Encoding
属性设置为特定编码并发送CSCS
命令.您可以使用CSCS=?
AT 命令询问支持的编码.即使应该应用默认的 GSM,我也会避免隐含地依赖它.- 您不需要在每个命令之后等待,但您必须等待调制解调器应答(检查
OK
或ERROR
字符串).
- Do not use
WriteLine()
butWrite()
because for SerialPort.WriteLine()
by default writes a usASCII encoded string but your GSM modem expect strings encoded as specified with an AT command. SetSerialPort.Encoding
property to a specific encoding and sendCSCS
command. You can ask supported encodings withCSCS=?
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
orERROR
strings).
来自 docs:
命令行由三个元素组成:前缀、正文和终止字符.命令行前缀由字符AT"或at"组成 [...] 终止字符可以由用户选项(参数 S3)选择,默认为 CR.
A command line is made up of three elements: the prefix, the body, and the termination character. The command line prefix consists of the characters "AT" or "at" [...] The termination character may be selected by a user option (parameter S3), the default being CR.
在伪代码中:
void SendCommand(string command) {
serialPort.Write(command + "
");
// 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
and
.
if (response.EndsWith("
OK
"))
break;
if (response.EndsWith("
> "))
break;
if (response.EndsWith("
ERROR
"))
break;
}
return response;
}
在发送命令之前添加 _receive.Reset()
,当然还要添加 OnPortDataReceived
作为 SerialPort.DataReceived
事件的处理程序:
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();
}
如果您遇到问题(但可以连接),您可以将
替换为
.某些调制解调器不正确(假设
没有使用 S3
参数映射到 13
以外的任何其他东西)默认情况下将此字符用作命令行终止符(即使它应该只出现在 V1
详细输出的输出中).更改您的代码或发送适当的 S3
.
If you have some trouble (but you can connect) you may replace
with
. 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)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!