2

我开发了一个 C# 应用程序来读取来自 GSM 调制解调器的呼叫。我使用计时器定期读取端口并在有来电时通知我。

现在我正在尝试使用另一个将写入AT+CSQ的计时器 - 要了解端口上的信号质量,并读取端口以获取质量值。在这两个计时器中,我都使用正则表达式来匹配和分离我需要的数据。现在的问题是,只有我正在读取信号质量的timer2才能正常工作,但不能读取来电的计时器。

定时器读取信号强度:

private void tmr_sig_quality_Tick(object sender, EventArgs e)
    {
        if (port.IsOpen)
        {
            port.WriteLine("AT+CSQ");
            string s= port.ReadExisting();
            var match= Regex.Match(s,@"\+CSQ: (\d+),(\d+)");
            if (match.Success)
            {
                progressBar1.Value = int.Parse(match.Groups[1].Value);
            }

        }
    }

计时器读取来电:

      private void timer1_Tick(object sender, EventArgs e)
       {
                s = port.ReadExisting();

                var match = Regex.Match(s, "RING[^\\+]*\\+CLIP:\\s*\"(?<phone>[^\"]*)\",(\\d+),\"([^\"]*)\",(\\w*),\"(\\w*)\",(\\w*)");

                if (match.Success && s.Contains("RING"))
                {
                    incall_status.Text = "Incoming Call...." + match.Groups["phone"].Value;
                    incall_status.Visible = true;
                }
        }

为什么会发生这种情况和解决方案?

4

2 回答 2

2

两个主要问题。首先是 ReadExisting(),它总是返回一个空字符串。除非您逐行调试和单步执行代码。这给了调制解调器足够的时间来发送响应。但是当您全速运行时,这将不起作用,您需要进行阻塞调用,以确保您的程序等待足够长的时间以获取所有返回的字符。请改用 ReadLine()。

第二个杀手问题是您正在混合命令。您的 tmr_sig_quality_Tick() 方法可能会读取 timer1_Tick() 应该读取的任何内容。您需要重新考虑这种方法。类似于命令队列,在收到对命令的响应之前不会前进。

于 2012-07-30T12:57:50.183 回答
1

不是您问题的实际答案,而是与 GSM 调制解调器通信的一般建议:

请记住,您只有一个串行端口,因此只有一个通信通道。GSM 调制解调器可以发送自发事件,例如 RING、FAX、VOICE 事件,因此无法保证当您编写 AT+CSQ 时,第一个回复是您所期望的,即信号质量。

像您打算的那样拥有两个计时器并不是一个好主意,因为您最终会在计时器 A 中得到一个命令的响应,而在 B 中是预期的,因为 A 读取了其中一个自发事件……等等。

一个更好和更健壮的方法是有一个工作线程来读取和解释传入的数据,然后根据需要将其分发到您的应用程序中。它还可以处理传出数据。使用并发队列和一些信号机制(即 AutoResetEvent)与该线程交换数据,这样您就可以获得与硬件设备的更清晰的接口,并且无需担心应用程序中的时间等问题。

于 2012-07-30T12:55:30.580 回答