2011-07-19 47 views
3

我有一個C程序,它打開一個COM端口的句柄,向它寫入一些字節,讀出一些字節,然後關閉句柄並退出。但是,當我連續運行10次程序時,開始花費很長時間才能完成GetCommState函數,並陷入SetCommState函數中。 C#中同樣的事情發生在一個簡單的SerialPort對象中。使用usbser.sys凍結SerialPort.Open/DeviceIoControl/GetcommState

我能找到的唯一修復方法是將設備重新連接到端口。有沒有更好的方法來擺脫這種凍結?這可能只是一些電腦配置錯誤?

我已經重寫代碼更新,以使其使用DeviceIoControl代替SetCommState。但是,這裏的問題完全相同。

device = 
    CreateFileW(
     L"\\\\.\\COM3", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 
     FILE_FLAG_OVERLAPPED, NULL); 

static int SetBaudRate (HANDLE device) { 
    int error = 0; 
    int success = 0; 
    OVERLAPPED overlapped = {0}; 
    overlapped.hEvent = CreateEvent(NULL, TRUE, 0, NULL); 
    if (overlapped.hEvent) { 
     SERIAL_BAUD_RATE baudRate = {0}; 
     baudRate.BaudRate = SERIAL_BAUD_115200; 
     error = 
      DeviceIoControl(
       device, IOCTL_SERIAL_SET_BAUD_RATE, &baudRate, 
       sizeof(SERIAL_BAUD_RATE), NULL, 0, NULL, &overlapped); 
     if (error || (!error && GetLastError() == ERROR_IO_PENDING)) { 
      DWORD bytes = 0; 
      if (GetOverlappedResult(device, &overlapped, &bytes, TRUE)) { 
       success = 1; 
      } 
     } 
    } 
    CloseHandle(overlapped.hEvent); 
    return success; 
} 

第一個問題:DeviceIoControl不會立即返回(雖然異步調用),並掛起了大約兩分鐘。 第二個問題:在這兩分鐘後,它會失敗,並顯示錯誤代碼121(ERR_SEM_TIMEOUT:「信號量超時期已過。」)。

  • 所使用的驅動程序是標準的Windows驅動程序usbser.sys
  • 爲什麼函數調用不立即返回任何想法?如果沒有,如何設置一個更短的超時功能?
  • 關於爲什麼函數失敗的任何想法?

更新2

樣品C#這也凍結(如上面的C程序)碼:

using System; 
using System.IO.Ports; 

sealed class Program { 
    static void Main (string[] args) { 
     int i = 0; 
     while (true) { 
      Console.WriteLine(++i); 
      SerialPort p = 
       new SerialPort("com3", 115200, Parity.None, 8, StopBits.One); 
      p.DtrEnable = true; 
      p.RtsEnable = true; 
      p.ParityReplace = 0; 
      p.WriteTimeout = 10000; 
      p.ReadTimeout = 3000; 
      try { 
       p.Open(); 
       Console.WriteLine("Success!"); 
      } catch (Exception e) { 
       Console.WriteLine(e.GetType().Name + ": " + e.Message); 
      } 
      p.Close(); 
      Console.ReadLine(); 
     } 
    } 
} 

樣品輸出如下:

1 (device not yet connected) 
IOException: The port 'com3' does not exist. 

2 (device connected but not yet in windows device manager) 
IOException: The port 'com3' does not exist. 

3 
IOException: The port 'com3' does not exist. 

4 (device connected and recognized) 
Success! 

5 
Success! 

[...] (with about one second between each enter press) 

15 
Success! 

16 (device still connected and recognized - nothing touched! after two minutes of freeze, semaphore timeout exactly as in the C version) 
IOException: The semaphore timeout period has expired. 


17 (device disconnected during the two minutes of freeze. it then returns instantly) 
IOException: A device attached to the system is not functioning. 


18 (device still disconnected - note that the exception is a different one than the one in the beginning although it's the same case: device not connected) 
IOException: The specified port does not exist. 

19 
IOException: The port 'com3' does not exist. 
+0

當你說它「凍結系統」是「系統」只是你的程序或整個計算機? – Gabe

+0

只是程序。當我用調試器遍歷代碼時,GetCommState會在1分鐘後返回,並且SetCommState需要更長的時間,直到由於超時而失敗。 – Etan

+0

這是一個內置的串行端口,虛擬端口,USB串行端口或其他? – Gabe

回答

0

這是我的C++類的一個工作部分,用於處理串口通信改變了一點,以適應C和您的需求。如果它不適用於虛擬端口工作,那麼它可能是你的驅動程序是錯誤的

DCB SerialPortSettings; 
HANDLE SerialPort; 

int OpenPort(WCHAR* PortName,int BaudRate) 
{ 

    SerialPort = CreateFileW(PortName, 
     GENERIC_READ|GENERIC_WRITE, 
     0, 
     NULL, 
     OPEN_EXISTING, 
     FILE_FLAG_OVERLAPPED, 
     NULL); 

    if(SerialPort==INVALID_HANDLE_VALUE) 
     return -2; 

    RtlZeroMemory(&SerialPortSettings,sizeof(DCB)); 
    SerialPortSettings.DCBlength = sizeof(DCB); 
    if(!GetCommState(SerialPort,&SerialPortSettings)) 
    { 
     CloseHandle(SerialPort); 
     return -3; 
    } 

    //8n1 RS485 
    SerialPortSettings.BaudRate = BaudRate; 
    SerialPortSettings.ByteSize = 8; 
    SerialPortSettings.Parity = NOPARITY; 
    SerialPortSettings.StopBits = ONESTOPBIT; 
    SerialPortSettings.fRtsControl = RTS_CONTROL_TOGGLE; 

    if(!SetCommState(SerialPort,&SerialPortSettings)) 
    { 
     CloseHandle(SerialPort); 
     return -4; 
    } 


    return 0; 

} 

編輯:嘗試從http://www.ftdichip.com/Drivers/VCP.htm下載驅動程序,因爲這個問題你描述的是最有可能是驅動程序或設備的問題。工作Etan :)

+0

我使用Windows附帶的標準驅動程序將USB設備連接到虛擬COM端口。問題不在於它根本不工作,而只是有時 - 例如,多次打開和關閉串口。我會爲這個問題添加一個簡單的C#示例,它會產生錯誤。 – Etan

+0

嘗試從http://www.ftdichip.com/Drivers/VCP.htm下載驅動程序,因爲您所描述的問題很可能是驅動程序或設備問題 – Djole

+1

您是否可以將此信息重新發布爲答案?該問題源自設備的錯誤固件。升級解決了凍結問題。 – Etan