【问题标题】:Strange serial port read/write behaviour奇怪的串口读/写行为
【发布时间】:2012-10-01 11:25:04
【问题描述】:

在我的 .Net 控制台应用程序中,我使用以下方法将少量字节(大约 20 个)写入串行端口,然后读取响应(同样不超过 20 个字节)。它用于与外部硬件设备通信 - 向其发送数据请求并返回请求的值。

我已经删除了多余的代码、端口初始化、变量声明等,但你仍然可以看到它在做什么:-

var sw = new Stopwatch();
sw.Start();

// Write the "request" bytes.
_port.Write(buffer, 0, buffer.Length);

Console.WriteLine("After write: {0}", sw.ElapsedMilliseconds);
sw.Restart();

// Wait for response, but timeout after 100ms.
var timeoutCount = 0;
while (_port.BytesToRead == 0 && timeoutCount < 100)
{
    Thread.Sleep(1);
    timeoutCount++;
}

Console.WriteLine("Waited: {0}, #loops: {1}", sw.ElapsedMilliseconds, timeoutCount);

if (_port.BytesToRead == 0)
{
    // Timed-out..
    return null;
}

// Read the response.
var receivedData = new byte[_port.BytesToRead];
_port.Read(receivedData, 0, receivedData.Length);

return receivedData;

我的应用程序以紧密(几乎连续)的循环调用上述代码。你会注意到我添加了几个 Console.WriteLines 来输出一些时间,我看到非常一致的数字,如下所示:-

After write: 0
Waited: 14, #loops: 1
After write: 0
Waited: 14, #loops: 1
After write: 0
Waited: 14, #loops: 1
...and so on...

显然,写入发生得非常快,响应也很快到达,因为应用程序只经过一次 while 循环,尽管我对为什么它只完成一个 Thread.Sleep(1) 时显示 14 毫秒感到困惑.

更奇怪的是,如果我在 PC 上执行其他操作,例如打开另一个窗口、运行 Chrome,甚至只是移动鼠标,那么我会看到如下图:-

After write: 0
Waited: 4, #loops: 5
After write: 0
Waited: 2, #loops: 3
After write: 0
Waited: 2, #loops: 3
After write: 0
Waited: 1, #loops: 2
After write: 0
Waited: 3, #loops: 4

这更像是我对串行端口代码的期望,而不是我在 PC“空闲”时看到的神秘 14 毫秒。关于发生了什么的任何想法?

这给我带来了问题,因为我的应用程序需要每 100 毫秒执行大约 12 次写入/读取。您可以从第二组时序(每组几毫秒)中看到,这很容易实现,但是当 PC 处于“空闲”状态时,每次写入/读取需要 14 毫秒,导致我的应用程序经常丢失数据(在外部更新每 100 毫秒设备一次)。

【问题讨论】:

    标签: .net serial-port


    【解决方案1】:

    您似乎有实时要求,但您正在非实时系统(Windows)上进行开发。 Sleep(1) 只是告诉操作系统你的线程在至少 1ms 内不能被重新激活,所以它会消失至少 1ms,当调度程序到达它时它会回来。

    您的鼠标移动似乎使其表现更好的原因是因为它导致调度程序被所有鼠标移动事件更频繁地调用。

    考虑使用实时操作系统,或者不依赖窗口进行调度,但如果您的 _port.write() 阻塞了诸如 WaitForSingleObject 或 Sleep 之类的系统调用,这可能会很困难。你也可以考虑放弃任何实时要求,只要你得到它就从串行端口得到什么。

    【讨论】:

    • 因此,即使鼠标事件发生在不同的窗口中,它仍然使调度程序“服务”我的应用程序更频繁?有没有办法控制/配置调度程序以达到类似的结果? (我尝试将我的应用程序的进程优先级设置为“高”,但没有任何区别)。
    • 就像我上面说的那样,快速而肮脏的方法是不依赖windows进行调度,换句话说:不要调用sleep(或其他阻塞调用)。是的,你会消耗大量的 CPU,是的,操作系统可能仍然会从你那里抽出 CPU 来服务其他事情(因此你仍然不能保证 100% 的时间满足你的时序要求),但你会在大多数情况下满足它们时间...这与您无需使用实时系统即可获得的时间一样好...
    猜你喜欢
    • 1970-01-01
    • 2023-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多