[英]Getting Serial communication Overrun error indication using WinAPI
概述:我試圖通過在從串行端口讀取的每個字節之間發出長延遲來觸發溢出錯誤指示。 長話短說 - 我不明白這個事件。
測試:DTE配置為920000BPS 8N1,無流量控制。 DTE 通過“Silicon Labs CP210x USB to UART Bridge”設備連接到我的 Windows10 主機。
提供的代碼片段打開端口,調用 SetCommMask 函數。 在循環內每次調用 ReadFile 之間插入了 10 秒的延遲。 DTE 以穩定的速率持續發送數據。
問題:我沒有從 WaitCommEvent 得到任何溢出信號。
問題:我的代碼有問題嗎? USB 驅動程序是否有一些已知的限制? 我是否需要使用流控制來注意到溢出事件?
#include <Windows.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
HANDLE hComm; // Handle to the Serial port
BOOL Status; // Status
DCB dcbSerialParams = { 0 }; // Initializing DCB structure
COMMTIMEOUTS timeouts = { 0 }; //Initializing timeouts structure
char SerialBuffer[64] = { 0 }; //Buffer to send and receive data
DWORD BytesWritten = 0; // No of bytes written to the port
DWORD dwEventMask; // Event mask to trigger
char ReadData; //temperory Character
DWORD NoBytesRead; // Bytes read by ReadFile()
unsigned char loop = 0;
wchar_t pszPortName[10] = { 0 }; //com port id
wchar_t PortNo[20] = { 0 }; //contain friendly name
//Enter the com port id
do
{
printf_s("Enter the Com Port: ");
wscanf_s(L"%s", pszPortName, (unsigned)_countof(pszPortName));
swprintf_s(PortNo, 20, L"\\\\.\\%s", pszPortName);
//Open the serial com port
hComm = CreateFile(PortNo, //friendly name
GENERIC_READ | GENERIC_WRITE, // Read/Write Access
0, // No Sharing, ports cant be shared
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
if (hComm == INVALID_HANDLE_VALUE)
{
printf_s("\n Port can't be opened\n\n");
break;
}
//Setting the Parameters for the SerialPort
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
Status = GetCommState(hComm, &dcbSerialParams); //retreives the current settings
if (Status == FALSE)
{
printf_s("\nError to Get the Com state\n\n");
break;
}
dcbSerialParams.BaudRate = 920000;//CBR_9600; //BaudRate = 9600
dcbSerialParams.ByteSize = 8; //ByteSize = 8
dcbSerialParams.StopBits = ONESTOPBIT; //StopBits = 1
dcbSerialParams.Parity = NOPARITY; //Parity = None
Status = SetCommState(hComm, &dcbSerialParams);
if (Status == FALSE)
{
printf_s("\nError to Setting DCB Structure\n\n");
break;
}
//Setting Timeouts
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (SetCommTimeouts(hComm, &timeouts) == FALSE)
{
printf_s("\nError to Setting Time outs");
break;
}
//Setting Receive Mask
Status = SetCommMask(hComm, EV_ERR| EV_RX80FULL| EV_BREAK/*EV_RXCHAR*/);
if (Status == FALSE)
{
printf_s("\nError to in Setting CommMask\n\n");
break;
}
//Read data and store in a buffer
do
{
Status = ReadFile(hComm, &ReadData, sizeof(ReadData), &NoBytesRead, NULL);
//Setting WaitComm() Event
Sleep(10000); /* Ten seconds */
Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received
if (Status == FALSE)
{
printf_s("\nError! in Setting WaitCommEvent()\n\n");
break;
}
SerialBuffer[loop] = ReadData;
++loop;
} while (NoBytesRead > 0);
--loop; //Get Actual length of received data
printf_s("\nNumber of bytes received = %d\n\n", loop);
//print receive data on console
printf_s("\n\n");
int index = 0;
for (index = 0; index < loop; ++index)
{
printf_s("%c", SerialBuffer[index]);
}
printf_s("\n\n");
} while (0);
CloseHandle(hComm);//Closing the Serial Port
system("pause");
return 0;
}
即使在接口芯片和設備驅動程序緩沖區已滿后,發送數據時也會發生串行端口溢出錯誤。
窄定義溢出只會發出接口芯片(8250/16550/etc)檢測到的信號。
因此,即使您花費很長時間來調用 ReadFile,也不清楚它是否會發生。
請嘗試以下操作。
使用重疊模式進行異步處理。
將所有 DCB 流量控制規范設置為 False
DCB 結構 (winbase.h)
在 SetupComm 中將緩沖區大小設置為最小值
SetupComm 函數 (winbase.h)
確保在 GetCommProperties 中正確設置
GetCommProperties 函數 (winbase.h)
COMMPROP 結構 (winbase.h)
不要調用 ReadFile
在設備驅動屬性的高級設置中禁用FIFO緩沖區或將閾值設置為最小大小
您需要調用 ClearCommError 以獲取有關所發生錯誤的更多信息。
ClearCommError 函數 (winbase.h)
但是,無論您做什么,如果您使用的是USB串行轉換芯片,則可能不會發生。
在嘗試上述方法的同時,請詢問芯片供應商是否有溢出錯誤或者是否可以檢測到,如果有,如何嘗試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.