为了账号安全,请及时绑定邮箱和手机立即绑定

串口基本流给出部分/扰乱/重复的数据

串口基本流给出部分/扰乱/重复的数据

C#
茅侃侃 2023-12-17 16:51:41
我目前正在编写一个简单的应用程序,它将通过 ftdi232 芯片(串行端口)与基于 arduino 的设备进行通信我在基流读取方面遇到了困难 - 我的应用程序在虚拟端口(com0com)上测试时运行良好,但是当我切换到 ftdi 设备时,接收到的数据变得混乱和/或重复。发送和接收端口配置相同:19200波特率8 个数据位奇偶校验 = 无停止位 = 1dtr 和 rts 被禁用DiscardNull 已启用。目前(测试)两个 ftdi 板都连接到同一台机器。 板通过 3 条线连接(rx、tx [交叉] 和接地)。有问题的方法:public async Task StartReceivingAsync()    {        _isLissening = true;        string errorData = string.Empty;        byte[] mainBuffer = new byte[_completeCommandSizeWithSep];        while(_port.IsOpen && !_receiveToken.IsCancellationRequested)        {                            int bytesRead = await _port.BaseStream.ReadAsync(mainBuffer, 0, _completeCommandSizeWithSep, _receiveToken);                            string rawData = Encoding.GetEncoding(_port.Encoding.CodePage).GetString(mainBuffer);            if(_port.Encoding.CodePage == Encoding.ASCII.CodePage)                _receivedBuffer.Append(RemoveNonAsciiChars(rawData));            else                _receivedBuffer.Append(rawData);            if(_receivedBuffer.Length >= _completeCommandSizeWithSep)            {                ICommandModel command = _commandModelFac();                string workPiece = _receivedBuffer.ToString(0, _completeCommandSizeWithSep);                int whereToCut = CheckRawData(workPiece);                if(whereToCut == -1)                {                    command.Data = workPiece;                    _receivedBuffer.Remove(0, _completeCommandSizeWithSep);                }                else if(whereToCut > 0)                {                    command.Data = _receivedBuffer.ToString(0, whereToCut);                    _receivedBuffer.Remove(0, whereToCut);                }                   
查看完整描述

1 回答

?
开心每一天1111

TA贡献1836条经验 获得超13个赞

我找到了解决办法!

StartReceivingAsync方法byte[] mainBuffer中初始化一次。
初始化后会出现“一会儿...”实际流读取数据的循环。

我不知道 FTDI 芯片的确切规格,但在不断发送时,它确实会以相当随机的部分发送数据(发送方和接收方没有超时)

所以,执行时
int bytesRead = await _port.BaseStream.ReadAsync(mainBuffer, 0, _completeCommandSizeWithSep, _receiveToken);
我会收到发送的数据的随机部分。该数据将按照预期写入 mainBuffer 字节数组,然后将其添加到 _receivedBuffer

事情来了:mainBuffer 当流接收到小于 _completeCommandSizeWithSep 的数据部分时,不会被清理。
BaseStream 读取器只是从 0 索引处替换收到的 mainBuffer 中的尽可能多的字符,忽略其余部分。

解决方法是仅添加长度等于 bytesRead 的子字符串 值而不是整个 mainBuffer 到接收缓冲区:

int bytesRead = await _port.BaseStream.ReadAsync(mainBuffer, 0, _completeCommandSizeWithSep, _receiveToken);


Bad code:

string rawData = Encoding.GetEncoding(_port.Encoding.CodePage).GetString(mainBuffer);


Working code:

string rawData = Encoding.GetEncoding(_port.Encoding.CodePage).GetString(mainBuffer).Substring(0, bytesRead);

替代解决方案是在 While 循环内重新初始化mainBuffer 数组。


查看完整回答
反对 回复 2023-12-17
  • 1 回答
  • 0 关注
  • 61 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信