冻结串行端口.使用usbuser .sys打开/ DeviceIoControl / GetcommState



我有一个C程序,它打开一个COM端口的句柄,向它写入一些字节,读取一些字节,然后关闭句柄并退出。然而,当我连续运行程序10次时,它开始花很长时间来完成GetCommState函数,并被困在SetCommState函数中。同样的事情也发生在c#中一个简单的SerialPort对象。

我能找到的唯一修复方法是将设备重新连接到端口。有什么更优雅的方法来摆脱这种冻结吗?也许只是电脑配置错误?

我重写了代码,使其使用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.

这是我的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工作过:)

最新更新