Разбор непрерывного входящего байтового массива из последовательного порта - PullRequest
0 голосов
/ 03 апреля 2020

У меня есть входящий байтовый массив в реальном времени, который имеет следующий формат:

Заголовок: 3 байта

Сообщение: 10 байтов

Заголовок: 3 байта

сообщение: 10 байт

и т. Д.

Проблема в том, что это непрерывный поток, который я не могу предсказать, когда придет заголовок, поскольку я мог бы начать читать входящие байты с часть сообщения или заголовка. Поэтому я был бы признателен, если бы кто-нибудь мог помочь мне в том, как перехватить заголовок и затем остаться в синхронизации c, используя событие dataReceived.

Редактировать: я пытался использовать счетчик для проверки каждого входящего байта в качестве заголовка, затем установите порог срабатывания после получения полезной нагрузки.

  1. Установите входной порог срабатывания на 1 байт
  2. Проверьте первый, второй заголовки
  3. Получите полезную нагрузку, если заголовки обнаруживаются и устанавливаются триггер входящего порогового значения для полезной нагрузки.
  4. Анализируют полезную нагрузку, снова устанавливают пороговое значение равным 1 байту.

Несмотря на то, что это не плохо, это не надежно с каждым входящим кадры в отличие от программного обеспечения, такие как serialplot

    private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                byte data = 0;
                if (_syncCounter < 3)
                {
                    data = (byte)_serialPort.ReadByte();
                }
                switch (_syncCounter)
                {
                    case 0: // First Byte in Header
                        _syncCounter = data == (byte)0xAA ? (byte) 1 : (byte) 0;
                        break;
                    case 1: // Second Byte in Header
                        _syncCounter = data == (byte)0xBB ? (byte)2 : (byte)0;
                        break;
                    case 2:
                        // Payload
                        _syncCounter = data == (byte)data ? (byte)3 : (byte)0;
                        if (_syncCounter == 3)
                        {
                            _serialPort.ReceivedBytesThreshold = data;
                            _payload = data;
                        }
                        break;
                    case 3:
                        // Packet
                        var packet = Enumerable.Repeat((byte)0x00, _payload).ToArray();
                        byte[] fieldBytes;
                        float fieldFloat;
                        _serialPort.Read(packet, 0, _payload);
                        if (packet.Length < _payload)
                        {
                            _serialPort.ReceivedBytesThreshold = 1;
                            _syncCounter = 0;
                            _payload = 0;
                        }
                        else
                        {
                            if (_isFirstPayload)
                            {
                                _syncCounter = 0;
                                _payload = 0;
                                _isFirstPayload = false;
                                break;
                            }
                            for (uint i = 0; i <= (_payload-1); i += 4)
                            {
                                fieldBytes = Slice(packet, i, i+4);
                                fieldFloat = ReadSingleBigEndian(fieldBytes, 0);
                                if (fieldFloat < 0)
                                    fieldFloat = 0;
                                _sb.Append(fieldFloat.ToString(CultureInfo.InvariantCulture));
                                _sb.Append(",");
                            }
                            IncomingFrame.BeginInvoke(() =>
                            {
                                IncomingFrame.Text = ByteArrayToString(packet);
                                if (_sb.Length > 0)
                                {
                                    _sb.Remove(_sb.Length - 1, 1);
                                    FloatFields.Text = _sb.ToString();
                                }
                                _sb.Clear();
                                _serialPort.ReceivedBytesThreshold = 1;
                                _syncCounter = 0;
                            });
                        }
                        break;
                }


 }

Проблема в том, что иногда я получаю заголовок как часть полезной нагрузки, хотя из кода, который я написал, он должен быть отфильтрован перед чтением полезной нагрузки .

Я проверил тот же ответ, используя serialplot, и он синхронизируется, что означает, что аппаратное обеспечение отправляет данные в соответствии с ожиданиями и анализируется правильно.

...