Geler sur SerialPort.Open / DeviceIoControl / GetcommState avec usbser.sys

J’ai un programme C qui ouvre un handle sur un port COM, lui écrit des octets, lit certains octets, ferme le handle et quitte. Cependant, lorsque j’exécute le programme dix fois de suite, l’ GetCommState fonction GetCommState et le GetCommState fonction GetCommState prennent beaucoup de temps. La même chose se produit en C # avec un object SerialPort simple.

Le seul correctif que j’ai pu trouver est de reconnecter le périphérique au port. Existe-t-il un moyen plus élégant de se débarrasser de ce gel? Est-ce peut-être juste une erreur de configuration du PC?

Mettre à jour

J’ai réécrit le code pour lui faire utiliser DeviceIoControl au lieu de SetCommState . Cependant, c’est exactement le même problème ici.

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

Premier problème: DeviceIoControl ne retourne pas immédiatement (bien que appelé asynchrone) et se bloque pendant environ deux minutes. Deuxième problème: le code d’erreur 121 échoue (ERR_SEM_TIMEOUT: “Le délai de temporisation du sémaphore a expiré.”) Après ces deux minutes.

  • Le pilote utilisé est le pilote Windows standard usbser.sys
  • Aucune idée sur pourquoi l’appel de fonction ne revient pas immédiatement? Et si non, comment définir un délai d’attente plus court pour la fonction?
  • Une idée sur pourquoi la fonction échoue?

Mise à jour 2

Exemple de code C # qui gèle également (comme le programme C ci-dessus):

 using System; using System.IO.Ports; sealed class Program { static void Main (ssortingng[] 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(); } } } 

Un exemple de sortie est le suivant:

 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’est une partie fonctionnelle de ma classe c ++ pour la gestion de la communication par port série qui a un peu changé pour prendre en charge le C et vos besoins. Si cela ne fonctionne pas, alors c’est probablement votre pilote pour le port virtuel qui est défectueux

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

Modifier: essayez de télécharger un pilote à partir de http://www.ftdichip.com/Drivers/VCP.htm , car le problème que vous décrivez est très probablement un problème de pilote ou de périphérique. Travaillé pour Etan 🙂