当通信通过实际串行端口时,以下代码按预期工作。进程阻塞ReadFile并等待串行缓冲区填充,然后继续处理。
但是,当我连接模拟串行端口的USB设备时,即使没有数据通过缓冲区,ReadFile也不会阻塞。
从USB连接设备每秒钟我得到以下输出......
rVal = 1 ch = -52 bytesRead = 0
因此,在通过usb端口发送字节之前,不会返回错误并且字节读取始终为0。
DWORD rVal;
HANDLE handle;
BOOL isGood;
char Ch; //Temporary character used for reading
DWORD bytesRead;
handle = CreateFile(L "\\\\.\\COM4", //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
if (handle == INVALID_HANDLE_VALUE)
{
return INVALID_HANDLE_VALUE;
}
isGood = SetCommMask(handle, EV_RXCHAR);
if (isGood == false)
{
return USV_ERR_READER_COM;
}
rVal = ReadFile(handle, //Handle of the Serial port
&ch, //Temporary character
sizeof(ch),//Size of TempChar
&bytesRead, //Number of bytes read
NULL);
...
答案 0 :(得分:-1)
问题在于我没有得到或设置通讯超时。 WinFI for ReadFile声明应该设置它,如果没有设置,行为是不可预测的。现在,下面的代码在多个串行设备上一致地工作。
对于降级此事的人,请先低头。
// W32SerialLibrary.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include<windows.h>
#include<stdio.h>
#define SEL 4 // marks the end of the message. it should only appear after a NAK/ACK and never by itself.
#define ACK 6 // the last character before the end of the message
#define NAK 21 // the last character before the end of the message
#define GS 29 // indicates the start of a message.
#define MAX_BUFFER 512
void convertCharToWchar(const char *fromCharBuffer, wchar_t *toWcharBuffer, size_t toWcharBufferSize)
{
int i;
for (i = 0; fromCharBuffer[i] != '\0' && i < toWcharBufferSize; i++)
{
toWcharBuffer[i] = fromCharBuffer[i];
}
toWcharBuffer[i] = '\0';
}
int readMRZ(const char *portPath, char *mrzBuffer, const size_t mrzBuffer_size)
{
HANDLE hComm;
DCB dcbSerialParams;
BOOL isGood;
COMMTIMEOUTS commTimeOuts;
char mrzChar; //Temporary character used for reading
DWORD bytesRead;
int mrzIndex;
DWORD maskUsed;
char errorChar = '_';
wchar_t wportPath[MAX_PATH];
convertCharToWchar(portPath, wportPath, sizeof(wportPath));
hComm = CreateFile(wportPath, //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
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("Error in opening serial port\n");
return -1;
}
// setup connection
dcbSerialParams = { 0 }; // Initializing DCB structure
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
isGood = GetCommState(hComm, &dcbSerialParams);
dcbSerialParams.BaudRate = CBR_9600; // Setting BaudRate = 9600
dcbSerialParams.ByteSize = 8; // Setting ByteSize = 8
dcbSerialParams.StopBits = ONESTOPBIT;// Setting StopBits = 1
dcbSerialParams.Parity = NOPARITY; // Setting Parity = None
// setup listener
isGood = SetCommState(hComm, &dcbSerialParams);
if (isGood == false)
{
printf("Error %d\n", GetLastError());
return -1;
}
GetCommTimeouts(hComm, &commTimeOuts);
isGood = SetCommMask(hComm, EV_RXCHAR);
if (isGood == false)
{
printf("Error %d\n", GetLastError());
return -1;
}
mrzIndex = 0;
commTimeOuts.ReadTotalTimeoutConstant = 0;
commTimeOuts.ReadTotalTimeoutMultiplier = 0;
commTimeOuts.WriteTotalTimeoutConstant = 0;
commTimeOuts.WriteTotalTimeoutMultiplier = 0;
commTimeOuts.ReadIntervalTimeout = 500;
SetCommTimeouts(hComm, &commTimeOuts);
maskUsed = 0;
WaitCommEvent(hComm, &maskUsed, NULL);
commTimeOuts.ReadIntervalTimeout = 0;
do
{
isGood = ReadFile(hComm, //Handle of the Serial port
&mrzChar, //Temporary character
sizeof(mrzChar), //Size of TempChar
&bytesRead, //Number of bytes read
NULL);
// printf("isGood %d ch=%c dec=%d oct=%#o hex=%#08X maskUsed=%x bytesRead=%d\n", isGood, mrzChar, mrzChar, mrzChar, mrzChar, maskUsed, bytesRead);
if (mrzChar == GS)
{
mrzIndex = 0;
continue;
}
if (mrzChar == ACK)
{
mrzBuffer[mrzIndex] = '\0';
break;
}
// fill buffer
if ((mrzChar >= 48 && mrzChar <= 90) || mrzChar == '<' || mrzChar == errorChar || mrzChar == '\r')
{
if (mrzIndex == MAX_BUFFER)
{
exit(-1);
}
if (mrzChar == '\r')
{
mrzBuffer[mrzIndex++] = '\n';
}
mrzBuffer[mrzIndex++] = mrzChar;
}
}
while (bytesRead > 0);
CloseHandle(hComm);//Closing the Serial Port
return 0;
}
int main()
{
char mrzBuffer[512];
int rVal;
rVal = readMRZ("\\\\.\\COM1", mrzBuffer, sizeof(mrzBuffer));
printf("\nrVal=%d mrzBuffer length=%d\n", rVal, strlen(mrzBuffer));
printf("mrzBuffer=\n\"%s\"\n", mrzBuffer);
return rVal;
}