【问题标题】:How can I detect the last character of GSM modem response如何检测 GSM 调制解调器响应的最后一个字符
【发布时间】:2014-02-09 22:15:51
【问题描述】:

我正在使用 GSM 调制解调器“SIM900” 我用超级终端测试过,主命令没问题。

然后我烧写了代码,通过 UART 发送 AT 命令以在微控制器上拨打一个号码到 GSM 调制解调器,它工作正常。

但我的回复有问题。 GSM 以字符流回复,但不以 Null '\0' 结尾!

如何获取数组中的整个响应以便稍后解析?还有,如何检测响应结束?

AT\r\n 响应 ==> OK

AT+CMGR=1 响应 ==> +CMGR: "REC UNREAD" ,"+2347060580383","10/10/27,18:54:32+04"

提前致谢。

【问题讨论】:

  • mmm 通过实践我发现响应 OK 实际上是 OK 所以我通过这个函数 void uartrecieve(unsigned char *data1) {无符号字符 i=0; while(1) { *data1 = recieve(); if(*data1 == '\n') i++; if((*data1 == '\n') && (i == 2)) 中断;数据1++;但是其他命令...具有不同数量的 \r\n 的不同响应,因此有一种通用方法可以解析具有相同功能的所有响应???????
  • 检查模块的数据表,但响应可能是\r\n+CMGR <other data>\r\n。此外,如果您在“文本模式”下阅读短信,如果它是多行短信,则消息中还可能包含 \r\n 字符。

标签: c embedded gsm modem


【解决方案1】:

您可以使用\r\nOK 作为结尾,因为电话使用\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();
    }
}

【讨论】:

    【解决方案2】:

    测试换行符,典型的是\n\r\n

    NUL0'\0')仅在 C 中用于终止字符数组,即“字符串”。

    【讨论】:

    • mmm 通过实践我发现响应 OK 实际上是 OK 所以我通过这个函数 void uartrecieve(unsigned char *data1) {无符号字符 i=0; while(1) { *data1 = recieve(); if(*data1 == '\n') i++; if((*data1 == '\n') && (i == 2)) 中断;数据1++;但其他命令...具有不同数量的 \r\n 的不同响应,因此有一种通用方法可以解析具有相同功能的所有响应??????? – 所以你知道 AT+CMGR 响应中的 \r\n 到底是什么吗???
    • @MGaafar:Standards 的好处是有这么多……:\ - 在这里阅读:en.wikipedia.org/wiki/Hayes_command_set#Syntactical_definitions 可能是开始在丛林中寻找线索的一个点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多