COM-порт запрещен - PullRequest
       1

COM-порт запрещен

4 голосов
/ 06 декабря 2010

Привет! Я пытаюсь использовать COM-порт для чтения некоторых регистров по протоколу Modbus, все работает нормально, пока я не перезагружаю ведомое устройство Modbus, затем у меня появляется ошибка, в которой com запрещен, я могу перезагрузить компьютер или отключить иобратно в «USB для Com Converter».Похоже, это устройство не справляется с com-портом должным образом.

using (port = new SerialPort(comPort))
{
   ushort[] registers = null;
   try
   {
      port.BaudRate = boudRate;
      port.DataBits = 8;
      port.Parity = Parity.None;
      port.StopBits = StopBits.One;
      port.Open();

      // modbus reading registers

      port.Close();
      return registers;
   }
   catch (Exception e)
   {
      Logs.AddToLog(e.Message);
      return registers;
   }
}

Ответы [ 2 ]

3 голосов
/ 07 декабря 2012

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

Ссылка Грега на управляемую оболочку FTDI была очень полезной, но предоставленный им фрагмент не совсем там, потому что для ссылки на устройство FTDI требуется немного больше кода. С его идеей в качестве отправной точки я адаптировал некоторый пример кода из FTDI и написал эту функцию. Он смог вернуть мое устройство FTDI в рабочее состояние без физического вмешательства.

/// <summary>
/// Attempts to reset an attached FTDI device and returns true if successful.  Note that a
/// 5-8 second delay is recommended after the reset.
/// </summary>
/// <returns></returns>
private bool ResetFTDI() {
  UInt32 ftdiDeviceCount = 0;
  FTD2XX_NET.FTDI.FT_STATUS ftStatus = FTD2XX_NET.FTDI.FT_STATUS.FT_OK;

  // Create new instance of the FTDI device class
  FTD2XX_NET.FTDI myFtdiDevice = new FTD2XX_NET.FTDI();
  // Determine the number of FTDI devices connected to the machine
  ftStatus = myFtdiDevice.GetNumberOfDevices(ref ftdiDeviceCount);
  // Check status
  if (ftStatus != FTD2XX_NET.FTDI.FT_STATUS.FT_OK) {
    Log.WriteLog("Failed to get number of FTDI devices [" + ftStatus.ToString() + "]");
    return false;
  }
  // If no devices available, return
  if (ftdiDeviceCount == 0) {
    Log.WriteLog("Failed to find any FTDI devices [" + ftStatus.ToString() + "]");
    return false;
  }
  // Allocate storage for device info list
  FTD2XX_NET.FTDI.FT_DEVICE_INFO_NODE[] ftdiDeviceList = new FTD2XX_NET.FTDI.FT_DEVICE_INFO_NODE[ftdiDeviceCount];
  // Populate our device list
  ftStatus = myFtdiDevice.GetDeviceList(ftdiDeviceList);
  if (ftStatus != FTD2XX_NET.FTDI.FT_STATUS.FT_OK) {
    Log.WriteLog("Failed enumerate FTDI devices [" + ftStatus.ToString() + "]");
    return false;
  }
  // Open first device in our list by serial number
  ftStatus = myFtdiDevice.OpenBySerialNumber(ftdiDeviceList[0].SerialNumber);
  if (ftStatus != FTD2XX_NET.FTDI.FT_STATUS.FT_OK) {
    Log.WriteLog("Failed to open device [" + ftStatus.ToString() + "]");
    return false;
  }
  // Finally, reset the port
  myFtdiDevice.CyclePort();
  return true;
}

Приведенный выше объект Log является внутренним для моего проекта, поэтому замените все, что вам подходит.

Некоторые дальнейшие исследования также подняли этот вопрос . В ответах Зак Соу упоминает проблему, обнаруженную им в связи .NET SerialPort. Я собираюсь попробовать его решение, и я опубликую здесь, если это полностью решит проблему, потому что я считаю, что вышеупомянутое является чем-то вроде бандаида.

3 голосов
/ 06 декабря 2010

Если вы используете адаптер FTDI USB / Serial, вы можете получить состояние непосредственно из управляемой оболочки ( FTDI Managed Driver Wrapper ) и повторно инициализировать ваш последовательный порт на основе подключенного состояния.

Простите, что я не имел опыта работы с устройствами FTDI, но это должно привести к сбросу вашего адаптера R-232:

FTD2XX_NET.FTDI device = new FTD2XX_NET.FTDI();
string port;
device.GetCOMPort(out port);

if (!string.IsNullOrEmpty(port) && (port.Equals(target)) && device.IsOpen)
{
    device.CyclePort();
    device.ResetDevice();
    device.ResetPort();
}

Насколько я понимаю, device.CyclePort() закроет любое активное соединение (звонки FT_CLOSE), размонтирует USB-устройство и повторно перечислит устройство с шины USB. Это должно быть точно так же, как если бы вы физически удалили и заново вставили адаптер.

Кроме того, в соответствии с документацией для оболочки Perl для библиотеки устройств FTDI:

Как и в случае с другими элементами управления шиной, есть период ожидания 5-8 секунд после CyclePort, где любой вызов API, который требует прямого подключения к устройство, например GetSerialByIndex () и т. д. потерпит неудачу с FT_INVALID_HANDLE пока он полностью не стабилизируется. Приложение должно учитывать этот период ожидания, или настроить опрос цикл, чтобы обнаружить изменение в ответ состояние.

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