让多个线程轮询同一个串口的正确方法是什么?

时间:2016-05-09 17:47:22

标签: c# multithreading user-interface serial-port polling

我很擅长与硬件交互。我目前正在使用Windows窗体在C#中构建GUI。我使用串口/ usb与硬件设备进行交互。我想要实现的是让多个线程在不同的时间轮询设备。应定期(至少每秒)检索一些数据,如温度,电流,功率等,并在GUI上更新,供用户查看。而只有当用户按下表单上的按钮时才会检索其他数据。多线程是否是解决此问题的正确方法?如果没有,什么是更好的解决方案?非常感谢例子。谢谢你们的时间!

更新:我正在尝试使用SerialPort.DataReceived事件,因为很多人都建议使用了终结符字符' \ r'解析串口的个别回复。然后我调用一个名为DisplayText的方法来处理该字符串。我现在的问题是我不知道如何弄清楚字符串代表什么。它代表温度,电流等吗?

private char terminator = '\r';
private void SerialPorts_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        try
        {
            output += serialPort1.ReadExisting();
            if (output.IndexOf((char)this.terminator) > -1)
            {
                string workingString = output.Substring(0, output.IndexOf(terminator));

                output = output.Substring(output.IndexOf(terminator) + 1);

                this.Invoke(new EventHandler((s, a)=>DisplayText(s, a, workingString)));
            }

        }

        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    private void DisplayText(object sender, EventArgs e, string s)
    {
        Console.WriteLine(s); // for testing only
        richTextBox1.AppendText(s); // for testing only
    }

3 个答案:

答案 0 :(得分:1)

我认为让多个线程轮询单个端口并尝试同步不是一个好主意。

最好有一个线程执行轮询,并将所有值存储在某个“中间”对象(单个,静态字段,您喜欢的内容)中,然后同步对此存储的访问。

所以一个线程轮询端口,收集值并将它们存储在某个地方,而不是其他线程从那里获取值。

答案 1 :(得分:0)

您可以使用互斥锁保护所有串行端口访问功能,并设计应用程序,使得在每次离散操作(例如读取温度)后串行端口关闭。一种可行的方法是编写一个包装API,其中包括:

  • 检查互斥锁是否已解锁(如果已锁定,则返回错误代码),

  • 打开串口

  • 阅读所需的值

  • 关闭串口并清除互斥锁

  • 返回读取值

然而,您正在使用此解决方案打开各种各样的死锁,您必须实施其他应用程序级别检查以防止这种情况。

如上所述,更好的解决方案是让单个线程定期轮询串行端口并持续更新您选择的数据结构中的所有值。

对于仅在用户输入后需要读取的值,您必须实现MessageQueue来请求此数据。

响应OP编辑进行更新

我建议您使用以下两种方法之一来接近设备中的通信:

  1. 实施请求/响应机制,您可以在其中发送请求 通过串口连接到您的设备的特定数据值(例如当前), 设备解析此请求并返回相应的值
  2. 让您的设备返回"框架中的所有值"例如     [SOF] [D0 ... Dn] [EOF],其中" D0 ... Dn"是你的所有数据     预先确定的序列; SOF和EOF可以是你的任何值     选择(你也可以选择完全跳过这些并依赖于     用于分隔帧的字节数。)
  3. 如果您无法选择 更改设备中的代码,则必须存在某种顺序,其中值由设备如此保持接收数据的序列号将是要走的路。但是,如果不了解设备正在做什么的更多细节,就很难提出解决方案。

答案 2 :(得分:0)

  

我现在的问题是我不知道如何弄清楚字符串是什么   代表。它代表温度,电流等吗?

使用简单的协议发送温度,电流等。

  

SOH + DATA + ETX + BCC

SOH = 0x02;

ETX = 0x03;

BCC = 0x00-0xFF,所有DATA + ETX的XOR值。

DATA =使用';'作为温度(温度)和电流(曲线)之间的分隔符

  

示例:

TempCmd = 0x01

TempValue = 32 celcius = 0x20

CurrCmd = 0x02

CurrValue = 1,4安培= 0x0E - >结果必须在接收器上除以10。

  

SOH + DATA + ETX + BCC

     

SOH + TempCmd:TempValue; CurrCmd:CurrValue + ETX + BCC

     

02 + 01:20; 02:0E + 03 + BCC

BCC = 01 xor':' xor 20 xor';' xor 02 xor':' xor 0E xor 03

  • 从微控制器发送数据" 0201:20; 02:0E03; XX" (以字符串形式发送)

  • 在计算机中接收数据:

    1. 检测包中的SOH和ETX
    2. 验证BCC为true(已完成包)或false(已打包)
    3. 解析数据; as delimiter // data1 = 01:20 data2 = 02:0E03
    4. 使用以下内容解析data1和data2:as delimiter // data1 = 20 data2 = 0E03
    5. 将十六进制转换为十进制,并将data2除以10以获取浮动格式的当前值。