2015-09-12 3 views
1

У меня есть микроконтроллер (Arduino Uno), работающий nanopb, который отправляет сообщения protobuf по проводу. Я нахожу, что в одном конкретном случае я не получаю свое полное сообщение. Некоторое время я думал, что это микроконтроллер, но, похоже, он находится на стороне C#, которая читает его.Последовательный порт не читает все данные

Проблема ТОЛЬКО для значений uint32 БОЛЬШЕ, ЧЕМ 16. 16 или менее, и работает нормально.

Я установил ОЧЕНЬ простую программу на микроконтроллере, чтобы убедиться, что это не мой другой код, вызывающий его. По сути, это посылает на структуру на провод с одним значением uint32_t в нем:

//Protobuf message: 
message Test { required uint32 testInt = 1 } 

//Resulting struct: 
typedef struct Test { 
    uint32_t testInt; 
} 

//Serial code: 
Serial.begin(115200); 
pb_ostream_t ostream; 

//Removed ostream setup code as it's not relevant here... 

Test message; 
Test.testInt = 17; 
pb_encode_delimited(&ostream, Test_fields, &message); 

Если я включаю в устройстве и посмотреть на это выходные данные с помощью Termite я вижу следующие данные (что правильно):

[02] [08] [11] (note Termite displays it in hex) 

(это говорит сообщение длиной 2 байта, а затем стартовым тзд байт, за которым следует значение Test.testInt 17 - 0x11 в шестнадцатеричной)

Теперь, если я поднимаю это в C# я см. 3 байта при чтении сообщения, но я вижу только 2. Когда va LUE в testInt составляет 16 или менее попадается, как три байта, 17 или более, и я получаю только два:

var port = new SerialPort("COM7", 115200, Parity.None, 8, StopBits.One); 
port.Handshake = Handshake.RequestToSendXOnXOff; 
port.Open(); 
while (port.IsOpen) 
{ 
    Console.WriteLine(port.ReadByte()); 
    Thread.Sleep(10); 
} 
port.Close(); 
Console.ReadLine(); 

Output with 16: 2 8 16 
Output with 17: 2 8 17 

Любая помощь очень ценится, я теряюсь в этот = (

ответ

1

Вы устанавливаете последовательный порт для использования Xon/Xoff. Зачем?

Код для XON является 17.

При передаче двоичных данных, не используйте XON/XOFF.

+0

BINGO - geez, который заставлял меня BONKERS ... Я использовал Xon/Xoff для установления связи, но он выглядит например, мне нужно использовать другой процесс, а не –

+1

Да, никто не использовал Xon/XOff, так как мы перестали использовать телетайпы :) 'serialPort.RtsEnable = true' - это то, что я использовал с моими устройствами Arduino. –

+1

Если вам требуется управление потоком, и вы не можете использовать рукопожатие HW, то (с дополнительными усилиями) XON/XOFF все еще можно использовать с двоичными данными, но вам нужен метод * вылета * значений данных 0x11 и 0x13. – sawdust

1

Похоже на простое условие гонки - нет ничего, чтобы гарантировать, что код C# получит 3 байта. Он может получить один, два, три или более. Если, скажем, он начинает цикл, когда два байта находятся в буфере UART, тогда он получит два байта и выведет их. Я подозреваю, что проблема 16/17 - это просто совпадение.

Кроме того, когда в буфере нет ничего, ваш цикл потребляет 100% -ный процессор. Это не хорошо.

Вам будет лучше использовать блокирующий вызов SerialPort.ReadByte(), получить длину байта, а затем цикл, чтобы прочитать, что еще много байтов из последовательного порта.

Кроме того, в качестве протокола использование сообщений protobuf в одиночку без заголовка не очень велико. Если вы выходите из синхронизации, это может занять много времени, прежде чем вам повезет, и вы сможете вернуться к синхронизации. Возможно, вы захотите добавить какой-то «магический байт» или последовательность магических байтов в начале каждого сообщения, чтобы читатель мог восстановить синхронизацию.

+0

Что касается цикла - да, это очень простое тестовое приложение, которое не предназначено для реального использования. Для записи я использую 'SerialPort.ReadByte()' в моем действительном коде, но для этой демонстрации я просто использовал ее как буфер - оба не работают одинаково. Но это не могло быть условием гонки, поскольку буфер последовательного порта должен ловить все байты, и это приложение должно выплевывать следующий набор байтов в следующем цикле вправо? Также почему это будет работать, когда у меня есть значение «16» или меньше на int, но ВСЕГДА терпят неудачу со значением 17 или выше. –

+0

. Что он зацикливает до того, как «все байты» были отправлены? Ваш компьютер намного быстрее, чем Arduino, он вернется и увидит только два байта, захватит их, выйдет, а затем вернется и получит еще один. –

+0

Право, это не проблема.если он вернется и получит еще один, я получаю все байты, но только два попадаются. см. мой обновленный вопрос для более простого приложения C#, которое все еще демонстрирует проблему. еще раз отметим, что это всего лишь пример, а не фактический производственный код - просто показать, что даже на самом базовом уровне серийного чтения он получает только два байта, когда все мои последовательные мониторы показывают три байта –

Смежные вопросы