[英]Getting Serial communication Overrun error indication using WinAPI
Overview: I'm trying to trigger an Overrun error indication, by issuing long delays between each byte read from the serial port.概述:我试图通过在从串行端口读取的每个字节之间发出长延迟来触发溢出错误指示。 To make long story short - I don't get this event.
长话短说 - 我不明白这个事件。
The test: The DTE is configured to work at 920000BPS 8N1, no flow control.测试:DTE配置为920000BPS 8N1,无流量控制。 The DTE is connected to my Windows10 host via "Silicon Labs CP210x USB to UART Bridge" device.
DTE 通过“Silicon Labs CP210x USB to UART Bridge”设备连接到我的 Windows10 主机。
The provided code fragment opens the port, calls the SetCommMask function.提供的代码片段打开端口,调用 SetCommMask 函数。 A delay of 10 seconds was inserted between each call to ReadFile within a loop.
在循环内每次调用 ReadFile 之间插入了 10 秒的延迟。 The DTE continuously sends data at a stable rate.
DTE 以稳定的速率持续发送数据。
The problem: I don't get any Overrun signal from WaitCommEvent.问题:我没有从 WaitCommEvent 得到任何溢出信号。
Question: Is there a problem with my code?问题:我的代码有问题吗? is there some known limitation with the USB driver?
USB 驱动程序是否有一些已知的限制? Do I need to use flow control to get noticed about overrun events?
我是否需要使用流控制来注意到溢出事件?
#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;
}
Serial port overrun errors should occur as data is sent even after the interface chip and device driver buffers are full.即使在接口芯片和设备驱动程序缓冲区已满后,发送数据时也会发生串行端口溢出错误。
And a narrow definition overrun will only signal what the interface chip(8250/16550/etc) has detected.窄定义溢出只会发出接口芯片(8250/16550/etc)检测到的信号。
So it's unclear if it will occur even if you take a long interval to call ReadFile.因此,即使您花费很长时间来调用 ReadFile,也不清楚它是否会发生。
Please try the following.请尝试以下操作。
Use the overlapped mode for asynchronous processing.使用重叠模式进行异步处理。
Set all DCB flow control specifications to False将所有 DCB 流量控制规范设置为 False
DCB structure (winbase.h) DCB 结构 (winbase.h)
Set the buffer size to the minimum value in SetupComm在 SetupComm 中将缓冲区大小设置为最小值
SetupComm function (winbase.h) SetupComm 函数 (winbase.h)
Make sure it is set correctly in GetCommProperties确保在 GetCommProperties 中正确设置
GetCommProperties function (winbase.h) GetCommProperties 函数 (winbase.h)
COMMPROP structure (winbase.h) COMMPROP 结构 (winbase.h)
Do not call ReadFile不要调用 ReadFile
Disable the FIFO buffer or set the threshold to the minimum size in the advanced settings of the device driver properties在设备驱动属性的高级设置中禁用FIFO缓冲区或将阈值设置为最小大小
You need to call ClearCommError to get more information about the error that occurred.您需要调用 ClearCommError 以获取有关所发生错误的更多信息。
ClearCommError function (winbase.h) ClearCommError 函数 (winbase.h)
However, no matter what you do, it may not occur if you are using a USB serial conversion chip.但是,无论您做什么,如果您使用的是USB串行转换芯片,则可能不会发生。
At the same time as trying the above, please ask the chip vendor if there is an overrun error or if it may be detected, and if so, how to try it.在尝试上述方法的同时,请询问芯片供应商是否有溢出错误或者是否可以检测到,如果有,如何尝试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.