我正在使用GSM调制解调器"SIM900“,我已经用超级终端测试过它,主命令也可以。
然后,我使用UART将代码发送给AT命令,在单片机上拨一个号码给GSM调制解调器,它工作得很好。
但我的反应有点问题。GSM回复的字符流,但它不以空'\0‘结束!
如何获得数组中的整个响应,以便稍后解析它?我怎样才能检测到回应的结束呢?
AT\r\n响应为==> OK
AT+CMGR=1响应为==> +CMGR:"REC“、"+2347060580383”、“10/10/27、18:54:32+04”
提前谢谢。
发布于 2014-02-14 15:44:57
您可以使用\r\nOK作为结尾,因为手机只对NewLine使用\n。但是有一种更可靠的方法(我做过一次)来确保您不会得到错误的结尾,例如当传入的文本消息中包含了确切的\r\nOK时。为了做到这一点,我建议您将字符集更改为UCS2,这样就可以在UnicodeArray中获得消息文本和发件人号(就像被转义了一样)。
下面是我使用的类(额外的检查模块(AT\r命令)用于防止陷入错误,以防出现意外错误或类似的情况!)我的模块有时没有响应,所以我可以让它再次响应!似乎不符合逻辑,但救了我!现在对我来说是完美的!)
public class SMSController
{
public event EventHandler StatusChanged;
protected virtual void OnStatusChanged()
{
if (StatusChanged != null)
{
StatusChanged(this, EventArgs.Empty);
}
}
SerialPort serial;
public SMSController(SerialPort serialPort)
{
this.serial = serialPort;
}
string readLine(int timeout = -1)
{
int oldTo = serial.ReadTimeout;
serial.ReadTimeout = timeout;
string str = serial.ReadTo("\n").Replace("\n", "").Replace("\r", "");
serial.ReadTimeout = oldTo;
return str;
}
void writeLine(string str)
{
serial.Write(str + "\r\n");
}
bool waitForString(string str, int timeout = -1)
{
if (readLine(timeout).Contains(str))
{
return true;
}
return false;
}
bool waitForOK(int timeout = -1, bool repeat = true)
{
if (repeat)
{
readUntilFind("OK", timeout);
return true;
}
else
return waitForString("OK", timeout);
}
void readUntilFind(string str, int timeout = -1)
{
while (!waitForString(str, timeout)) ;
}
void writeCommand(string command)
{
serial.DiscardInBuffer();
writeLine(command);
}
bool applyCommand(string command, int timeout = -1)
{
writeCommand(command);
return waitForOK(timeout);
}
private string lastStatus = "Ready";
public string LastStatus
{
get { return lastStatus; }
private set
{
lastStatus = value;
OnStatusChanged();
}
}
public void InitModule()
{
try
{
LastStatus = "Checking SIM900...";
applyCommand("ATE0", 2000); //Disable echo
applyCommand("AT", 5000); //Check module
LastStatus = "Initializing SIM900...";
applyCommand("AT+CMGF=1", 1000); //Set SMS format to text mode
LastStatus = "Operation successful!";
}
catch (TimeoutException)
{
LastStatus = "Operation timed-out";
}
catch (Exception ex)
{
LastStatus = ex.Message;
}
}
public static string ConvertToUnicodeArray(string str)
{
byte[] byt = Encoding.Unicode.GetBytes(str);
string res = "";
for (int i = 0; i < byt.Length; i+=2)
{
res += byt[i + 1].ToString("X2");
res += byt[i].ToString("X2");
}
return res;
}
public void SendMessage(string destinationNumber, string text, bool isUnicode = false)
{
try
{
LastStatus = "Initiating to send...";
applyCommand("AT+CSMP=17,167,2,25", 1000);
if (isUnicode)
{
if (!applyCommand("AT+CSCS=\"UCS2\"", 5000))
throw new Exception("Operation failed!");
writeCommand("AT+CMGS=\"" + ConvertToUnicodeArray(destinationNumber) + "\"");
}
else
{
if (!applyCommand("AT+CSCS=\"GSM\"", 5000))
throw new Exception("Operation failed!");
writeCommand("AT+CMGS=\"" + destinationNumber + "\"");
}
waitForString("> ", 5000);
LastStatus = "Sending...";
serial.DiscardInBuffer();
serial.Write(isUnicode ? ConvertToUnicodeArray(text) : text);
serial.Write(new byte[] { 0x1A }, 0, 1);
if (waitForOK(30000))
{
LastStatus = "Message sent!";
}
else
LastStatus = "Sending failed!";
}
catch (TimeoutException)
{
LastStatus = "Operation timed-out";
}
catch (Exception ex)
{
LastStatus = ex.Message;
}
}
private string readTo(string str, int timeout)
{
int to = serial.ReadTimeout;
serial.ReadTimeout = timeout;
string strread = serial.ReadTo(str);
serial.ReadTimeout = to;
return strread;
}
public static byte[] StringToByteArray(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
public static string ConvertUnicodeToText(string bytes)
{
byte[] bt = StringToByteArray(bytes);
for (int i = 0; i < bt.Length; i+=2)
{
byte swap = bt[i];
bt[i] = bt[i + 1];
bt[i + 1] = swap;
}
return Encoding.Unicode.GetString(bt);
}
public SMS[] GetUnreadMessages()
{
List<SMS> lst = new List<SMS>();
try
{
LastStatus = "Initializing...";
applyCommand("AT+CSMP=17,167,2,25", 1000);
applyCommand("AT+CSCS=\"UCS2\"", 2000);
LastStatus = "Fetching text messages...";
writeCommand("AT+CMGL=\"REC UNREAD\"");
string texts = readTo("OK\r\n", 10000);
string[] packets = texts.Split(new string[] { "\r\n\r\n" }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < packets.Length; i++)
{
if (!packets[i].Contains("+CMGL"))
continue;
string num = packets[i].Split(new string[] { "," },
StringSplitOptions.RemoveEmptyEntries)[2].Replace("\"", "");
string txt = packets[i].Split(new string[] { "\r\n" },
StringSplitOptions.RemoveEmptyEntries)[1].Replace("\"", "");
lst.Add(new SMS(ConvertUnicodeToText(num), ConvertUnicodeToText(txt)));
}
applyCommand("AT+CMGDA=\"DEL READ\"", 10000);
LastStatus = "Operation successful!";
}
catch (TimeoutException)
{
LastStatus = "Operation timed-out";
}
catch (Exception ex)
{
LastStatus = ex.Message;
}
return lst.ToArray();
}
}发布于 2014-02-09 22:21:08
测试一个新行,典型的是\n或\r\n.
NUL (0或'\0')仅在C中用于终止字符数组,即“字符串”。
https://stackoverflow.com/questions/21665789
复制相似问题