Заморозить на SerialPort.Open / DeviceIoControl / GetcommState с помощью usbser.sys
У меня есть программа на 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.
1 ответ
Это рабочая часть моего класса 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, поскольку описываемая вами проблема, скорее всего, связана с драйвером или устройством. Работал на Итана:)