Базовый поток последовательного порта дает частичные / зашифрованные / дублированные данные - PullRequest
1 голос
/ 22 сентября 2019

В настоящее время я пишу простое приложение, которое будет взаимодействовать с устройством на базе Arduino с помощью микросхем ftdi232 (последовательный порт)

Я столкнулся со стеной с базовым чтением - мое приложение отлично работает при тестировании на виртуальных портах(com0com), но когда я переключился на устройства ftdi, полученные данные стали зашифрованными и / или дублированными.

И отправляющий, и принимающий порты настроены одинаково:

  • 19200 бод
  • 8 бит данных
  • четность = нет
  • стоп-биты = 1
  • DTR и 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);
                }                   

                if (whereToCut != 0)                    
                    command.CommandType = CommandType.Error;

                else
                {                        
                    command = CommandTranslator(workPiece);
                    _receivedBuffer.Remove(0, _completeCommandSizeWithSep);                        
                }   
                DataReceived?.Invoke(this, command);
            }
            else
            {
                continue;
            }                
        } 
        _isLissening = false;
    }

Способ отправки:

while (true)
            {
                serial.Write($@"*{"0015"}*" +  i.ToString().PadLeft(4, '0') + '*' + i.ToString().PadLeft(30, '.'));
                Console.WriteLine(serial.ReadExisting());

                i++;
                Console.WriteLine("...");
                Console.ReadLine();
            }

_completeCommandSizeWithSep - длина команды, которая должна быть получена.

Формат команды *0001* AAAA * 123456789123asdfgh12345678584a

Пример данных из переменной workPiece (почти ванильный, только символы не удалены) при отправке данных:

Отправленные данные:

*0015*0EF9*.............................0

*0015*2K3R*.............................1

*0015*C80S*.............................2

Полученные данные:

*0015*0EF9*.0EF9*.0EF9*.0EF9*.0EF9*.0EF9*
...F9*...F9*...F9*...F9*...F9*...F9*...F9
*...F9*...F9*...F9*...F9*...F9*...F9*...F
*...F9*...F9*...F9*...F9*...F9*...F9*...F
*...F9*...F9*...F9*...F9*...F9*...F9*...F
*...F9*...F9*...F9*...F9*...F9*...F9*...F
*...F9*...F9*...F9*...F9*...F9*...F9*...F
*...F9*...F9*...F9*...F9*...F9*...F9*...F
*...F9*...F9*...F9*...F9*...F9*...F9*...F
*...F9*...F9*...F9*...F9*...F9*...F9*...F
*...F9*...F9*...F9*...F9*...F9*...F9*...F
*...F9*...F9*...F9*...F9*...F9*...F9*...F
*...F9*...F9*...F9*...F9*...F9*...F9*...F
*...F9*...F9*...F9*...F9*...F9*...F9*...F
*...F9*...F9*...F9*...F9*...F9*...F9*...F
*...F9*...F9*...F9*...F9*...F9*...F9*0..F
*...F9*...F9*...F9*...F9*...F9*0..F9**..F
*...F9*...F9*...F9*...F9*0..F9**..F9*00.F
*...F9*...F9*...F9*0..F9**..F9*00.F9*10.F
*...F9*...F9*0..F9**..F9*00.F9*10.F9*50.F
*...F9*0..F9**..F9*00.F9*10.F9*50.F9**0.F
*0..F9**..F9*00.F9*10.F9*50.F9**0.F9*00.F
**..F9*00.F9*10.F9*50.F9**0.F9*00.F9*E0.F
*..F9*00.F9*10.F9*50.F9**0.F9*00.F9*E0.F9
*00.F9*10.F9*50.F9**0.F9*00.F9*E0.F9*F0.F
*10.F9*50.F9**0.F9*00.F9*E0.F9*F0.F9*90.F
*50.F9**0.F9*00.F9*E0.F9*F0.F9*90.F9**0.F
**0.F9*00.F9*E0.F9*F0.F9*90.F9**0.F9*.0.F
*0.F9*00.F9*E0.F9*F0.F9*90.F9**0.F9*.0.F9
*00.F9*E0.F9*F0.F9*90.F9**0.F9*.0.F9*...F
*E0.F9*F0.F9*90.F9**0.F9*.0.F9*...F9*....
*F0.F9*90.F9**0.F9*.0.F9*...F9*....9*....
*90.F9**0.F9*.0.F9*...F9*....9*....9*....
**0.F9*.0.F9*...F9*....9*....9*....9*....
*0.F9*.0.F9*...F9*....9*....9*....9*....9
*.0.F9*...F9*....9*....9*....9*....9*....
*...F9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*0...
*....9*....9*....9*....9*....9*0...9**...
*....9*....9*....9*....9*0...9**...9*0...
*....9*....9*....9*0...9**...9*0...9*01..
*....9*....9*0...9**...9*0...9*01..9*51..
*....9*0...9**...9*0...9*01..9*51..9**1..
*0...9**...9*0...9*01..9*51..9**1..9*21..
**...9*0...9*01..9*51..9**1..9*21..9*K1..
*...9*0...9*01..9*51..9**1..9*21..9*K1..9
*0...9*01..9*51..9**1..9*21..9*K1..9*31..
*01..9*51..9**1..9*21..9*K1..9*31..9*R1..
*51..9**1..9*21..9*K1..9*31..9*R1..9**1..
**1..9*21..9*K1..9*31..9*R1..9**1..9*.1..
*1..9*21..9*K1..9*31..9*R1..9**1..9*.1..9
*21..9*K1..9*31..9*R1..9**1..9*.1..9*.1..
*K1..9*31..9*R1..9**1..9*.1..9*.1..9*.1..
*31..9*R1..9**1..9*.1..9*.1..9*.1..9*.1..
*R1..9**1..9*.1..9*.1..9*.1..9*.1..9*....
**1..9*.1..9*.1..9*.1..9*.1..9*....9*....
*1..9*.1..9*.1..9*.1..9*.1..9*....9*....9
*.1..9*.1..9*.1..9*.1..9*....9*....9*....
*.1..9*.1..9*.1..9*....9*....9*....9*....
*.1..9*.1..9*....9*....9*....9*....9*....
*.1..9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*1...
*....9*....9*....9*....9*....9*1...9**...
*....9*....9*....9*....9*1...9**...9*0...
*....9*....9*....9*1...9**...9*0...9*0...
*....9*....9*1...9**...9*0...9*0...9*1...
*....9*1...9**...9*0...9*0...9*1...9*5...
*1...9**...9*0...9*0...9*1...9*5...9**...
**...9*0...9*0...9*1...9*5...9**...9*2...
*...9*0...9*0...9*1...9*5...9**...9*2...9
*0...9*0...9*1...9*5...9**...9*2...9*K...
*0...9*1...9*5...9**...9*2...9*K...9*3...
*1...9*5...9**...9*2...9*K...9*3...9*R*..
*5...9**...9*2...9*K...9*3...9*R*..9*.*..
**...9*2...9*K...9*3...9*R*..9*.*..9*.*..
*...9*2...9*K...9*3...9*R*..9*.*..9*.*..9
*2...9*K...9*3...9*R*..9*.*..9*.*..9*.*..
*K...9*3...9*R*..9*.*..9*.*..9*.*..9*.*..
*3...9*R*..9*.*..9*.*..9*.*..9*.*..9*.*..
*R*..9*.*..9*.*..9*.*..9*.*..9*.*..9*.*..
*..9*.*..9*.*..9*.*..9*.*..9*.*..9*.*..9*
*.*..9*.*..9*.*..9*.*..9*.*..9*.*..9*.*..
*..9*.*..9*.*..9*.*..9*.*..9*.*..9*.*..9*
*.*..9*.*..9*.*..9*.*..9*.*..9*.*..9*.*..
*..9*.*..9*.*..9*.*..9*.*..9*.*..9*.*..9*
*.*..9*.*..9*.*..9*.*..9*.*..9*.*..9*.*..
*..9*.*..9*.*..9*.*..9*.*..9*.*..9*.*..9*
*.*..9*.*..9*.*..9*.*..9*.*..9*.*..9*....
*..9*.*..9*.*..9*.*..9*.*..9*.*..9*....9*
*.*..9*.*..9*.*..9*.*..9*.*..9*....9*....
*..9*.*..9*.*..9*.*..9*.*..9*....9*....9*
*.*..9*.*..9*.*..9*.*..9*....9*....9*....
*..9*.*..9*.*..9*.*..9*....9*....9*....9*
*.*..9*.*..9*.*..9*....9*....9*....9*....
*..9*.*..9*.*..9*....9*....9*....9*....9*
*.*..9*.*..9*....9*....9*....9*....9*....
*..9*.*..9*....9*....9*....9*....9*....9*
*.*..9*....9*....9*....9*....9*....9*....
*..9*....9*....9*....9*....9*....9*....9*
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*....
*....9*....9*....9*....9*....9*....9*1...
*....9*....9*....9*....9*....9*1...9**...
*....9*....9*....9*....9*1...9**...9*0...
*....9*....9*....9*1...9**...9*0...9*01..
*....9*....9*1...9**...9*0...9*01..9*5*..
*....9*1...9**...9*0...9*01..9*5*..9*C8..
*1...9**...9*0...9*01..9*5*..9*C8..9*08..
**...9*0...9*01..9*5*..9*C8..9*08..9*S8..
*...9*0...9*01..9*5*..9*C8..9*08..9*S8..9
*0...9*01..9*5*..9*C8..9*08..9*S8..9**...
*01..9*5*..9*C8..9*08..9*S8..9**...9*....
*5*..9*C8..9*08..9*S8..9**...9*....9*....
*..9*C8..9*08..9*S8..9**...9*....9*....9*
*C8..9*08..9*S8..9**...9*....9*....9*....
*08..9*S8..9**...9*....9*....9*....9*....
*S8..9**...9*....9*....9*....9*....9*....
**...9*....9*....9*....9*....9*..........
*...9*....9*....9*....9*....9*...........
*....9*....9*....9*....9*................
*....9*....9*....9*......................
*....9*....9*............................
*....9*..................................
*........................................
....................2*....0*....015...*C5

Дополнительно - данные от прослушивателя порта:

1619781: 2019-09-21 23:37:52,7484713 +0,2099872

 2A 30 30 31 35 2A 30 45 46 39 2A 2E 2E 2E 2E 2E   *0015*0EF9*.....
 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E   ................
 2E 2E 2E 2E 2E 2E 2E 2E 30 2A 30 30 31 35 2A 30   ........0*0015*0
 45 46 39 2A 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E   EF9*............
 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E   ................
 2E 30                                             .0
1620349: 2019-09-21 23:37:54,4023089 +0,3609614

 2A 30 30 31 35 2A 32 4B 33 52 2A 2E 2E 2E 2E 2E   *0015*2K3R*.....
 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E   ................
 2E 2E 2E 2E 2E 2E 2E 2E 31 2A 30 30 31 35 2A 32   ........1*0015*2
 4B 33 52 2A 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E   K3R*............
 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E   ................
 2E 31                                             .1
1620937: 2019-09-21 23:37:54,8706713 +0,3255464

 2A 30 30 31 35 2A 43 38 30 53 2A 2E 2E 2E 2E 2E   *0015*C80S*.....
 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E   ................
 2E 2E 2E 2E 2E 2E 2E 2E 32 2A 30 30 31 35 2A 43   ........2*0015*C
 38 30 53 2A 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E   80S*............
 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E 2E   ................
 2

1 Ответ

0 голосов
/ 22 сентября 2019

Я нашел решение!

В StartReceivingAsync метод byte[] mainBuffer инициализируется один раз.После инициализации возникает цикл while ..., который выполняет реальное чтение данных в потоке.

Я не знаю точной спецификации для микросхем FTDI, но она отправляет данные довольно случайными частями при постоянной отправке (без таймаутов в отправителях и получателях)

Итак, при выполненииint bytesRead = await _port.BaseStream.ReadAsync(mainBuffer, 0, _completeCommandSizeWithSep, _receiveToken);Я бы получил случайную порцию отправленных данных.Эти данные будут, как и предполагалось, записываться в mainBuffer байтовый массив, который, в свою очередь, будет добавлен в _receivedBuffer.

И вот что необходимо: mainBuffer не очищается при получении потокачасть данных, которая меньше, чем _completeCommandSizeWithSep.Считыватель BaseStream просто заменяет столько символов в mainBuffer из индекса 0, сколько было получено, игнорируя остальные.

Исправление заключается в добавлении подстроки длины, равной значению 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);

Альтернативным решением будет повторная инициализация mainBuffer массива внутри цикла While.

...