小编Cra*_*ied的帖子

从USB串行端口读取时,SerialPort.BaseStream.ReadAsync丢弃或加扰字节

编辑:我已经添加了发送代码和接收到的输出示例。


我正在从连接到嵌入式系统的USB“虚拟”串行端口读取数据。我编写了两种接收数据的方法,一种是同步的,一种是异步的。同步的一个起作用,而异步的一个则丢失或加扰一些传入的数据。我不知道为什么第二个失败。

可以使用的方法调用将读取超时设置为零的SerialPort.Read,并请求接收缓冲区中的所有内容。我检查返回值以查看实际读取了多少字节,然后将数据放入循环缓冲区以供其他地方使用。此方法由计时器中断调用,它可以完美地接收串行数据(通常以高于1.6 Mbps的速率而无数据丢失)。但是,轮询计时器对我来说已成为一个问题,我希望在其余代码中异步接收数据。

丢失数据的方法在串行端口BaseStream上等待ReadAsync并循环直到取消。这种方法是可行的,但是它经常使数据包的前导字节不按顺序返回,相当频繁地丢失单个字节(大约每千个数据字节一次),并且偶尔从数据包中丢失数百个连续字节。

这里可能存在两个完全不同的问题,因为更大的数据丢失块的丢失似乎与更高的数据速率和更重的系统活动相关。问题的特定部分可能是由于缓冲区超限所致-可能是由于USB调度程序遇到延迟时USB握手失败-但我在此处显示的示例仅在50时传输了非常少量的数据毫秒间隔,除此测试例程外,系统处于空闲状态。

我观察到ReadAsync经常在一次读取时返回数据包的第一个字节,而在下次读取时返回数据包的其余部分。我相信这是预期的行为,因为MSDN表示如果一段时间内没有可用数据,则ReadAsync将返回其收到的第一个字节。但是,我认为这种行为与我的问题有某种关系,因为当单个字节丢失或顺序混乱时,它总是第一个字节“总是”,其余的数据包则正常到达。

当数据包较小时,通常(但并非总是)从数据包开头的“丢失”字节似乎在其余数据包之后的下一次读取中传送,这对我来说绝对没有意义。对于较大的数据包,仍然偶尔会发生这种情况,但是通常在数据包较大时,第一个字节会丢失。

我进行了广泛搜索,并阅读了有关该主题的所有SO问题。我发现其他人似乎也有类似的问题(例如:SerialPort.BaseStream.ReadAsync缺少第一个字节),但是没有人提供任何可接受的甚至合理的解决方案。

Ben Voigt(http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport)和其他似乎真正了解串行通信的人建议在基流上使用ReadAsync,微软的物联网团队也推荐了这种方法,因此我必须相信这种方法应该可行。

问题1:为什么我的代码在USB Serial BaseStream上使用ReadAsync会丢弃/加扰字节?

问题2:如果无法使ReadAsync可靠地以正确的顺序返回接收到的所有字节,我是否可以在传统的SerialPort周围放置一个异步包装器。读取并等待/循环它,这样就不必从计时器轮询?我读过这是个坏主意,但我也读过SerialPort类在内部是异步的,因此也许可以吗?还是我唯一的选择将它放在工作线程上并让它花所有时间等待?

我的代码如下。我已serialPort1.ReadTimeout = 0;serialPort1.BaseStream.ReadTimeout = 0;(我已经尝试过其他的持续时间)。我已经启用了RTS和DTR,并且由于这是一个USB_serial端口,因此它应该在内部处理握手,并且当我同步读取时肯定可以这样做-但是从BaseStream读取时可能不是这样吗?

这是第一种方法:

// this method works perfectly when called from a timer.
// SerialPort.ReadTimeout must be set to zero for this to work.
// It handles incoming bytes reliably at rates above 1.6 Mbps.

private void ReadSerialBytes()
{
    if (!serialPort1.IsOpen) …
Run Code Online (Sandbox Code Playgroud)

c# serial-port usbserial

7
推荐指数
1
解决办法
5880
查看次数

根据 size_t 测试循环变量时避免出现有符号/无符号警告的权威“正确”方法

下面的代码会生成编译器警告:

private void test()
{
    byte buffer[100];
    for (int i = 0; i < sizeof(buffer); ++i)
    {
        buffer[i] = 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

警告:有符号和无符号整数表达式之间的比较 [-Wsign-compare]

这是因为 sizeof() 返回一个无符号的 size_t。

我已经看到了许多关于如何处理这个问题的建议,但没有一个得到了压倒性的支持,也没有一个有任何令人信服的逻辑,也没有任何参考文献来支持一种明显“更好”的方法。最常见的建议似乎是:

  1. 忽略警告
  2. 关闭警告
  3. 使用 size_t 类型的循环变量
  4. 使用 size_t 类型的循环变量以及避免递减超过零的技巧
  5. 将 size_of(buffer) 转换为 int
  6. 一些极其复杂的建议,我没有耐心遵循,因为它们涉及不可读的代码,通常涉及向量和/或迭代器
  7. 我无法在我经常使用的 AVR / ARM 嵌入式环境中加载的库。
  8. 返回表示 T 字节数的有效 int 或 long 的自由函数
  9. 不要使用循环(一定喜欢这个建议)

有没有“正确”的方法来解决这个问题?

-- 开始编辑 --

当然,我给出的示例很简单,只是为了演示在索引情况下可能发生的类型不匹配警告。

#3不一定是明显正确的答案,因为 size_t 在递减循环中存在特殊风险,例如 for (size_t i = myArray.size; i > 0; --i) (数组的大小有一天可能为零)。

#4建议通过适当且必要的检查来处理 size_t 索引的递减,以避免递减超过零。由于这使得代码更难阅读,所以有一些可爱的快捷方式并不是特别可读,因此我将它们称为“技巧”。 …

c++

5
推荐指数
1
解决办法
1385
查看次数

如何计算 Visual Studio 2017 中选定(或找到)的字符和行数?

我正在开发一个组合的嵌入式 + 桌面应用程序。嵌入式平台上的内存限制使得了解将发送和接收的项目的大小和数量非常重要。当我在一个系统上更改大小或元素计数时,我需要与另一个系统协调这些更改。

为了获得这些信息,我目前在 Visual Studio 中选择并复制感兴趣的元素,并将它们粘贴到一个外部文本编辑器中,该编辑器可以为我提供字符数和行数。

我想找到一种方法来在 Visual Studio (2017) 中查看相同的信息(选定行数和选定字符数)。

到目前为止,我发现的唯一方法是在选择中执行查找和替换,它会报告替换次数。如果我使用正则表达式进行匹配,我可以获得任何匹配的计数,因此通过两次传递,我可以获得替换的字符和行数——但是我必须使用 Ctrl-Z 来消除损坏,这似乎就像一个坏主意。一定会有更好的办法。

除了使用“查找和替换”然后取消损坏之外,还有什么方法可以获取找到或选择的元素的数量?

几乎我见过的所有其他编辑器都允许在选择中进行“查找”并告诉您匹配数,但我没有找到任何方法让 Visual Studio 显示匹配数,即使所有找到的元素都是颜色标记。我必须做“全部替换”才能得到计数。

我看到几年前就有针对相同功能的定期功能请求,但到目前为止,由于缺乏投票,它们已被关闭。我发现 VS2010 的宏可以做到这一点,但我没有找到任何证据表明 VS2017 中存在宏。我还没有找到任何提供所选行数和所选字符数的市场扩展。

请注意,我不打算计算文件、项目或解决方案中的代码行数。我只是想在 Visual Studio IDE的选择中“动态”计算字符和行数。我进行了搜索,但没有发现任何与此问题重复的问题。

visual-studio

5
推荐指数
2
解决办法
4852
查看次数

标签 统计

c# ×1

c++ ×1

serial-port ×1

usbserial ×1

visual-studio ×1