Как я могу реализовать двухпроводную двунаправленную связь RS485 в .NET?

Я пытаюсь установить двунаправленную связь, используя 2 провода RS485, и все, что я пробовал до сих пор, не удалось.

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


Я использую .NET SerialPort, я пробовал использовать событие DataReceived, а также цикл в Thread опросе порта. Я даже пробовал просто блокировать чтение, пока не будет получено достаточно данных.


Я пробовал несколько вариантов оборудования:

  • Карта PCI RS232 с преобразователем Sena RS232-RS485
  • Карта PCI RS232 с преобразователем Moxa RS232-RS485
  • Карта PCI RS485

Я играл с настройками драйвера: - Уровни срабатывания прерывания FIFO - Пороги управления потоком FIFO приемника - Включение буфера RS485 (нормальный, активный высокий, активный низкий)


Следуя различным рекомендациям (например, Может не получаю последовательные данные в .net 2.0, используя преобразователь rs232 в rs485), я попытался установить DtrEnable в значение true или false или переключить его.

Я также пробовал переключать RtsEnable при отправке и получении (следуя http://en.wikipedia.org/wiki/RS-232#RTS.2FCTS_handshaking).


Я не вижу сейчас ничего другого, что можно было бы попробовать, не прибегая к другой разводке. Что могло быть не так?


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

Открытым:

_serialPort = new SerialPort(comboBoxSerialPort.Text, 9600, Parity.None, 8, StopBits.One)
{
    WriteTimeout = 500,
    ReadTimeout = 500,
    Handshake = Handshake.None
};

_serialPort.Open();
_serialPort.DtrEnable = true;
_serialPort.RtsEnable = true;

Послать:

_serialPort.RtsEnable = false;
_serialPort.Write(data, 0, data.Length);
_serialPort.RtsEnable = true;

Thread.Sleep(1);
_dataSent.Set();

Читатель ветки:

var port = form1._serialPort;
byte[] buffer = new byte[128];
int read = 0;
do
{
    Array.Clear(buffer, 0, buffer.Length);
    read = 0;

    try
    {
        form1._dataSent.WaitOne();

        //if (port.BytesToRead > 0)
        read = port.Read(buffer, 0, buffer.Length);
    }
    catch (TimeoutException)
    {
    }
    catch (Exception ex)
    {
        form1.Invoke(form1.AddErrorMethod, ex.ToString());
        continue;
    }

    if (read > 0)
    {
        form1.Invoke(form1.AddOutputMethod, ByteListToString(buffer));
    }

    Thread.Sleep(20);
}
while (_continue);

Примечание: пакеты данных имеют длину 10 байтов в обоих направлениях.


person jv42    schedule 04.09.2013    source источник
comment
О, и я открыт для использования реализации SerialPort P / Invoke, например, предложенной Скоттом Хансельманом здесь: hanselman.com/blog/, если это ошибка / ограничение .NET Framework.   -  person jv42    schedule 04.09.2013
comment
Один глупый вопрос: вы подтвердили, что устройство (периферийное устройство) действительно что-то отправляет по проводу? Если да, то показ вашего кода поможет нам вам в этом :)   -  person user2019047    schedule 04.09.2013
comment
@ user2019047, это совсем не глупо :) Я не могу подтвердить, что что-то идет по проводам, но производитель подтвердил, что в их настройке (не на ПК с Windows) периферийное устройство работает так, как задумано.   -  person jv42    schedule 04.09.2013
comment
Я вижу, вы отправляете сигнал почти сразу после отправки, и значение чтения, возможно, будет равно 0 при первом захвате сигнала. Если я правильно понимаю код, в следующий раз чтение будет выполнено, когда вы что-то отправите и снова отправите сигнал. пробовали ли вы точку останова на read = port. ... выражение, чтобы увидеть значение прочитанного? Может быть, обработчик полученных данных - лучший выбор?   -  person user2019047    schedule 04.09.2013
comment
@ user2019047 Да, я использовал сигнализацию для связи с фоновым потоком, выполняющим опрос SerialPort. Прочитано - это количество байтов, фактически прочитанных методом (см. msdn.microsoft.com /en-us/library/ms143549.aspx), всегда 0. Изначально он использовался для смещения в буфер.   -  person jv42    schedule 04.09.2013
comment
@ user2019047 Как упоминалось в моем первоначальном вопросе, я пробовал подход обработчика событий, событие никогда не запускалось.   -  person jv42    schedule 04.09.2013
comment
Тогда либо с вашего устройства ничего не передается (маловероятно?), Либо что-то неправильно настроено в последовательном драйвере. Какого подтверждения связи ожидает устройство? Я вижу, вы устанавливаете свойство RtsEnable из MSDN: сигнал запроса на передачу (RTS) обычно используется в аппаратном квитировании запроса на отправку / сброса для отправки (RTS / CTS). Может быть, из-за нескольких отправленных / полученных байтов квитирование не требуется? Кстати, код _serialPort = new SerialPort и т. Д. Не может компилироваться.   -  person user2019047    schedule 04.09.2013
comment
@ user2019047 Мне удалось получить ответ, используя одну очень специфическую конфигурацию оборудования (в этой конфигурации была проблема с проводкой) и используя DtrEnable вместо RtsEnable для переключения линии. Я дам исчерпывающий ответ, когда проверим все варианты. Спасибо за вашу помощь!   -  person jv42    schedule 05.09.2013


Ответы (1)


Я исправил проблему в одной конфигурации оборудования (карта RS485) следующим образом:

  • фиксация проводки: хотя это называется «2 провода», необходимо использовать 4 контакта / провода от карты, соединенные, 2 с помощью транспортного провода.
  • использование DtrEnable для указания отправки / получения
  • ожидание перед включением режима приема после отправки.

Мой код отправки теперь выглядит так:

// Enable send mode
SerialPort.DtrEnable = false;
SerialPort.Write(data, 0, data.Length);

// Wait a little, then enable response mode.
Thread.Sleep(15);
SerialPort.DtrEnable = true;
person jv42    schedule 06.09.2013
comment
Ожидание требуется, чтобы справиться с переключением канала RS-485. Пока передатчик включен (DTR false), ведомое устройство не может отправлять, но требуется настройка, чтобы сообщение было отправлено. Задержку необходимо настроить в соответствии с продолжительностью отправленного сообщения (при 9600 бит / с 10 байтов занимают чуть более 10 мс). Последовательная синхронизация затруднена на мультиплексированных каналах с высокоуровневым API. - person Pekka; 13.04.2014
comment
@Pekka Спасибо за комментарий. Я не думал о битрейте, чтобы вычислить необходимое время сна, это должно помочь мне повысить надежность. - person jv42; 14.04.2014