开发者

COM port is denied

Hi I am trying to use COM port to read some registers using modbus protocol, everything works fine until I rebote modbus slave device, then I have error that com is denied, what I can do is or rebot computer or plug out and back in 'usb to com converter'. Seems that this device doesn't handle with com port properly.

using (port = new SerialPort(comPort))
{
   ushort[] registers = null;
   try
   {
      port.BaudRate = boudRate;
      port.DataBi开发者_开发知识库ts = 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;
   }
}


If you are using an FTDI USB/Serial adapter, you can retrieve the state directly from the managed wrapper (FTDI Managed Driver Wrapper) and reinitialize your serial port based on the connected state.

Forgive my lack of experiance with FTDI devices, but this should reset your R-232 adapter:

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();
}

By my understanding device.CyclePort() will close any active connection (calls FT_CLOSE), unmounts the usb device, and reenumerates the device from the usb bus. This should be exactly the same as if you physically removed, and reinserted the adapter.

Also, according to the documentation for the Perl wrapper for the FTDI device library:

As with other bus controls, there is a wait period of 5-8 seconds after a CyclePort where any API call that requires direct connection to the device, like GetSerialByIndex() etc, will fail with FT_INVALID_HANDLE until it has completely stabilized. The application should account for this wait period, or setup a polling loop to detect the change in return status.


I had a similar experience where an FTDI device would enter a state where I couldn't communicate with it unless I physically unplugged it. Greg's answer helped me come up with a workaround.

Greg's reference to FTDI's managed wrapper was very helpful, but the snippet he provided isn't quite there because it takes a bit more code to actually reference an FTDI device. With his idea as a starting point, I adapted some example code from FTDI and wrote this function. It was able to put my FTDI device back into a working state without physical intervention.

/// <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;
}

The Log object above is internal to my project so substitute whatever suits you.

Some further research also turned up this question. In the answers, Zach Saw references a problem he discovered with .NET SerialPort communications. I'm going to try his solution and I'll post back here if that resolves the problem entirely because I consider the above to be something of a bandaid.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜