2010-12-06 337 views
4

嗨我想用COM端口來讀取一些使用modbus協議的寄存器,一切工作正常,直到我rebund modbus從屬設備,然後我有錯誤,COM被拒絕,我可以做的是或反彈計算機或者插入並返回'USB到COM轉換器'。似乎這個設備不能正確處理COM端口。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

你得到了什麼錯誤(你在哪裏得到它)? – KevinDTimm 2010-12-06 18:44:29

+0

它工作得很好,但是當我重新啓動我的modbus奴隸,並嘗試再次讀取,然後我有個例外,這個COM端口被拒絕 – kosnkov 2010-12-06 18:59:53

回答

3

如果您使用的是FTDI USB /串口適配器,可以直接從託管包裝(FTDI Managed Driver Wrapper)基於連接狀態找回狀態,並重新初始化串口。

原諒我的缺乏與FTDI設備的experiance,但是這應該重置您的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裝置庫中的文檔:

與其他總線的控制,有一個 CyclePort其中任何API之後的5-8秒 等待週期調用 需要直接連接到 設備,例如GetSerialByIndex() 等,將會失敗,FT_INVALID_HANDLE 直到它完全穩定。 應用程序應該佔用 這個等待期,或者設置一個輪詢 循環來檢測返回 狀態的變化。

3

我有一個類似的經驗,FTDI設備會進入一個狀態,我不能與它溝通,除非我物理拔掉它。格雷格的回答幫助我想出了一個解決方法。

Greg對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; 
} 

上面的日誌對象是我的項目的內部,所以替代任何適合你。

一些進一步的研究也出現了this question。在答案中,Zach Saw引用了他在.NET SerialPort通信中發現的一個問題。我會嘗試他的解決方案,如果能夠完全解決問題,我會在這裏回覆,因爲我認爲上述內容是一種帶band的方式。