Win32 串口编程(四)
7 通信超時
通信超時是影響讀寫操作的另一個重要方面。如果操作所用時間大于超時值,則操作完成,ReadFile、WriteFile、GetOverlappedResule或者WaitForSingleObject不會返回錯誤代碼,它們都指示操作成功完成。實際傳輸的字節數小于請求的字節數是操作超時的唯一指示。如果ReadFile返回TRUE,但是讀取到的字節數小于請求的字節數,則操作超時了。如果重疊寫操作超時,則重疊事件句柄受信,WaitForSingleObject返回WAIT_OBJECT_0;GetOverlappedResult返回TRUE,dwBytesTransferred指示超時前已經傳輸的字節數。下面的代碼展示了如何處理這種情況:
BOOL WriteABuffer(char * lpBuf, DWORD dwToWrite){? OVERLAPPED osWrite = {0};? DWORD dwWritten;? DWORD dwRes;? BOOL? fRes; ?? // Create this write operation's OVERLAPPED structure hEvent.? osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);? if (osWrite.hEvent == NULL)???? // Error creating overlapped event handle.???? return FALSE; ?? // Issue write? if (!WriteFile(hComm, lpBuf, dwToWrite, &dwWritten, &osWrite)) {???? if (GetLastError() != ERROR_IO_PENDING) { ??????? // WriteFile failed, but it isn't delayed. Report error.??????? fRes = FALSE;???? }???? else??????? // Write is pending.??????? dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);??????? switch(dwRes)??????? {?????????? // Overlapped event has been signaled. ?????????? case WAIT_OBJECT_0:??????????????? if (!GetOverlappedResult(hComm, &osWrite, &dwWritten, FALSE))????????????????????? fRes = FALSE;??????????????? else {???????????????? if (dwWritten != dwToWrite) {??????????????????? // The write operation timed out. I now need to ??????????????????? // decide if I want to abort or retry. If I retry, ??????????????????? // I need to send only the bytes that weren't sent. ??????????????????? // If I want to abort, I would just set fRes to ??????????????????? // FALSE and return.??????????????????? fRes = FALSE;???????????????? }???????????????? else??????????????????? // Write operation completed successfully.??????????????????? fRes = TRUE;?????????????? }??????????????? break;?????????? ?????????? default:??????????????? // An error has occurred in WaitForSingleObject. This usually ?????????????? // indicates a problem with the overlapped event handle.??????????????? fRes = FALSE;??????????????? break;??????? }???? }? }? else {???? // WriteFile completed immediately. ????? if (dwWritten != dwToWrite) {???????? // The write operation timed out. I now need to ???????? // decide if I want to abort or retry. If I retry, ???????? // I need to send only the bytes that weren't sent. ???????? // If I want to abort, then I would just set fRes to ???????? // FALSE and return.???????? fRes = FALSE;???? }???? else???????? fRes = TRUE;? } ?? CloseHandle(osWrite.hEvent);? return fRes;}SetCommTimeouts 用以設置端口的通信超時值;GetCommTimeouts獲取通信超時。下面是代碼示例:
COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout = 20;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.ReadTotalTimeoutConstant = 100;
timeouts.WriteTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 100;
if (!SetCommTimeouts(hComm, &timeouts))
?? // Error setting time-outs.
如果設置COMMTIMOUTS的各個成員為零,則不會發生超時。非重疊操作會阻塞直到請求的字節數傳輸完成:ReadFile會阻塞直到所有請求的字符到達端口;WriteFile會阻塞直到所有請求的字符被發送。重疊操作只有在所有字符已經傳輸,或者取消操作時才完成。只有操作完成時才發生下列條件:
- WaitForSingleObject always returns WAIT_TIMEOUT if a synchronization time-out is supplied. WaitForSingleObject will block forever if an INFINITE synchronization time-out is used.
- GetOverlappedResult always returns FALSE and GetLastError returns ERROR_IO_INCOMPLETE if called directly after the call to GetOverlappedResult.
Setting the members of the COMMTIMEOUTS structure in the following manner causes read operations to complete immediately without waiting for any new data to arrive:
COMMTIMEOUTS timeouts;timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadTotalTimeoutMultiplier = 0; timeouts.ReadTotalTimeoutConstant = 0; timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = 0;if (!SetCommTimeouts(hComm, &timeouts))// Error setting time-outs.These settings are necessary when used with an event-based read described in the "Caveat" section earlier. In order for ReadFile to return 0 bytes read, the ReadIntervalTimeout member of the COMMTIMEOUTS structure is set to MAXDWORD, and the ReadTimeoutMultiplier and ReadTimeoutConstant are both set to zero.
An application must always specifically set communications time-outs when it uses a communications port. The behavior of read and write operations is affected by communications time-outs. When a port is initially open, it uses default time-outs supplied by the driver or time-outs left over from a previous communications application. If an application assumes that time-outs are set a certain way, while the time-outs are actually different, then read and write operations may never complete or may complete too often.
總結
以上是生活随笔為你收集整理的Win32 串口编程(四)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js 原型以及原型链
- 下一篇: html自动适应屏幕分辨率,css如何自