2016-09-02 2 views
6

Извините, быстрый вопрос:Последовательный порт связи на той же машине Windows, не работает

У меня есть эта аппаратная настройка:

То же машина: "Com3" -> USB -> к серийному -> для USB -> "COM4"

и я последовал MSDN SerialPort Class и MSDN SerialPort.ReadLine() строить эту рутинную:

SerialPort SendSerialPort = new SerialPort("Com3", 9600); 
SerialPort ReceiveSerialPort = new SerialPort("Com4", 9600); 

SendSerialPort.Open(); 
ReceiveSerialPort.Open(); 

SendSerialPort.WriteLine("Test"); 
var message = ReceiveSerialPort.ReadLine(); // control stops here 

SendSerialPort.Close(); 
ReceiveSerialPort.Close(); 

Console.WriteLine(message); 

Однако, когда я склонен к ReadLine(), мой контроль останавливается и просто ждет. Я этого не ожидал.

Я ожидаю получить строку Test и назначить ее моему var message. Не могли бы вы рассказать мне, что я делаю неправильно здесь?

EDIT:

Я проверил мое оборудование, используя Serial Port Utility Application и it worked just fine.

+1

Вы не используете нити –

+1

Операции ввода-вывода блокируются. Вам нужно будет перенести хотя бы одну из ваших операций ввода-вывода в другой поток/Задачу. – rene

ответ

4

Я изменил from the example you linked:

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

Полезно использовать таймер.

public static void Main() 
{ 
    SerialPort SendSerialPort = new SerialPort("Com3", 9600); 
    SerialPort ReceiveSerialPort = new SerialPort("Com4", 9600); 

    StringComparer stringComparer = StringComparer.OrdinalIgnoreCase; 
    Thread readThread = new Thread(Read); 

    // Set the read/write timeouts 
    _serialPort.ReadTimeout = 500; 
    _serialPort.WriteTimeout = 500; 

    SendSerialPort.Open(); 
    ReceiveSerialPort.Open(); 
    bool _continue = true; 
    readThread.Start(); 

    Console.Write("Name: "); 
    name = Console.ReadLine(); 

    Console.WriteLine("Type QUIT to exit"); 

    while (_continue) 
    { 
     message = Console.ReadLine(); 

     if (stringComparer.Equals("quit", message)) 
      _continue = false; 
     else 
      SendSerialPort.WriteLine(String.Format("<{0}>: {1}", name, message)); 
    } 
    readThread.Join(); 
    SendSerialPort.Close(); 
} 

public static void Read() 
{ 
    while (_continue) 
    { 
     try 
     { 
      string message = ReceiveSerialPort.ReadLine(); 
      Console.WriteLine(message); 
     } 
     catch (TimeoutException) { } 
    } 
} 

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

Недостаточно и важна интизация ваших портов.

Я предпочитаю использовать конструктор по умолчанию (предпочтение только)

SerialPort Constructor() 

И затем установить любые значения, например, так:

_serialPort.BaudRate = SetPortBaudRate(_serialPort.BaudRate); 
_serialPort.Parity = SetPortParity(_serialPort.Parity); 
_serialPort.DataBits = SetPortDataBits(_serialPort.DataBits); 
_serialPort.StopBits = SetPortStopBits(_serialPort.StopBits); 
_serialPort.Handshake = SetPortHandshake(_serialPort.Handshake); 

Все Конструкторы дадут следующие значения:

This constructor uses default property values when none are specified. Например, свойство DataBits по умолчанию равно 8, свойство Parity по умолчанию равно None enume ration, значение свойства StopBits по умолчанию равно 1 и имя порта COM1 по умолчанию.

Даже рукопожатие имеет значение по умолчанию. Если вы look at the source code.

private const Handshake defaultHandshake = Handshake.None; 
+1

Я не мог воспроизвести проблему. Следовательно, я буду считать, что он был случайным, поскольку параметры 'DataBits',' StopBits' и 'Parity' [установлены по умолчанию] (http://stackoverflow.com/questions/39297839/are-uninitialised-attributes- данные ий умолчанию значение-как-они-являются-при-использование-на-размораживания). Я хочу убедиться, что этого больше не произойдет, поэтому я буду использовать рекомендованный выше метод нескольких потоков для непрерывного чтения и записи через последовательный порт. –

+1

@FirstStep Из первого экземпляра Если был тайм-аут или еще одна проблема с чтением, он мог бы там висели, вы не знали бы, не запустив его. И да, задача async или threading (как я уже говорил, задачи async используют потоки, за кулисами) или какой-то тип обработчика событий. Это интересно и с нетерпением ждем вашего развития. –

2

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

Имейте в виду, что просто установить Baudrate недостаточно, вы также должны использовать свойства DataBits, Parity и Stopbits в соответствии с настройками устройства. Несоответствие может вызвать ошибку, вид, который вы можете видеть только при написании обработчика событий для события ErrorReceived. Никогда не пропустите это событие, проблемы с запуском могут произойти, если вы никогда не проверяете.

И прежде всего свойство Handshake должно быть установлено правильно. Правильное значение зависит от того, как соединяются порты вместе, слишком часто, чтобы не подключать их. Начните с установки его Handshake.None, так что неправильное состояние для сигналов DSR и CTS не может блокировать прием, а неправильное состояние для сигналов DTR и RTS не может блокировать передачу. Остерегайтесь того, что для другой программы необходимо включить аппаратное квитирование, несовпадение гарантировано приведет к остановке связи.

Если вы используете синхронные чтения вместо события DataReceived, вы должны, в общем, иметь дело с возможностью того, что устройство не отвечает. Либо потому, что он выключен, не подключен вообще или не работает. Используйте свойство ReadTimeout для этого, чтобы ваша программа не зависала. Навыки высоки, 10000 миллисекунд - разумный выбор.

Остерегайтесь случайности этой проблемы, забирая другую программу, вы можете легко настроить порт правильно, и теперь он внезапно начнет работать. И будьте осторожны, что запуск нити ничего не выполняет, теперь будет тот поток, который застрял, а вызов Join() закроется.

+0

Один Q хотя: Вы рекомендуете необходимость нескольких потоков? Он работал над одной и той же нитью. Я предполагаю, что мне просто нужно убедиться в правильной/правильной конфигурации. –

+1

Я попытался предупредить вас в последнем абзаце, что использование потока не является решением. Так нет. Вам нужно сосредоточиться на настройке, вот ваша проблема. Rock-hard правило заключается в том, что вы никогда не можете воспользоваться ярлыком на нем. –

+0

Чтобы запустить его постоянно, потребуется выполнить задачу многопоточности или асинхронности. Это нормально для одного тестового прогона. В частности, если вы хотите отправлять данные между двумя портами. –

5

Проблема с кодом в этой строке

var message = ReceiveSerialPort.ReadLine(); 

блокировании код ждать линии, если линия не прибывает она останется здесь навсегда или значение, установленное в ReadTimeout

Так почему же линия никогда не прибывает?

Проблема может быть ошибка в WriteLine("Test");, вы должны обрабатывать ошибки, или это может быть, что ваш в преграждают ваш код ReadLine() до WriteLine("Test") удается пройти через, вы можете вставить Thread.Sleep(100) между ними, но это не действительно улучшая код.

Примечание: Ваш код также будет работать, как иногда, в зависимости от условий гонки.

Это синхронизированное/блокирующее чтение из последовательных портов кажется простым в коде только одной строкой; но он создает много негативных побочных эффектов в вашем протоколе связи.

Гораздо лучше (учитывая то, что вы хотите для чтения/записи данных из микроконтроллера) является либо использовать нить, как Yvette suggested или использовать асинхронно чтение Stream.BeginRead (Byte[], Int32, Int32, AsyncCallback, Object), который я предпочел бы.

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

В протоколе связи с асинхронно чтением AutoResetEvent очень полезно, поэтому вы посылаете что-то, то вы начинаете AutoResetEvent, если асинхронно ожидаемый результат прибывает вы будете установить это событие, и ваш код может продолжаться, если он не придет AutoResetEvent будет тайм-аут, и вы сможете справиться с этим.

+0

Благодарим вас за ответ. У меня есть Q, если вы не возражаете: если «_my line никогда не приходит», почему он так и не пришел и так долго? Мой код затем должен оставаться на 'Read()' для миллисекунд «_100_», скажем так, и продолжать, как только сообщения появятся. Что мне не хватает? –

+0

Возможно, это была ошибка при отправке, возможно, вы заблокировали отправку (у нее не было времени на запуск), прежде чем вы заблокировали ее в readLine (следовательно, readLine() фактически блокирует ваш код), а writeLine не является. –

+0

О, у него не было времени пройти на первом месте, и он получил «_interupted_». Понимаю. Спасибо за урок! –

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