我正在编写程序,以通过USB通过虚拟com端口与电机驱动器进行通信。我正在使用windows.h file-io与它进行通信(CreateFile,WriteFile,ReadFile)。我可以很好地写入驱动器,但是尝试读取驱动器时遇到问题。由于某种原因,ReadFile似乎只能从缓冲区读取一个字符。这是我的代码:
#define READ_BUFF_SIZE 500
#define READ_TIMEOUT 5000
void ReadInput(HANDLE hComm)
{
DWORD dwRead, dwRes;
BOOL fWaitingOnRead = FALSE;
OVERLAPPED osReader = {0};
char lpBuf[READ_BUFF_SIZE] = {0};
osReader.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
if(osReader.hEvent==NULL){
cerr<<"Error creating overlapped handle!";return;}
if(!fWaitingOnRead){
if(!ReadFile(hComm, lpBuf, READ_BUFF_SIZE, &dwRead, &osReader)){
if(GetLastError()!=ERROR_IO_PENDING)
{cout<<"Error: "<<GetLastError()<<endl;return;}
else
fWaitingOnRead = TRUE;
}
else {cout<<"a\n";PrintInput(lpBuf,dwRead);}
}
if(fWaitingOnRead){
dwRes = WaitForSingleObject(osReader.hEvent,READ_TIMEOUT);
cout<<"\n\nAfter WaitForSingleObject."<<endl;
switch(dwRes)
{
case WAIT_OBJECT_0:
if(!GetOverlappedResult(hComm,&osReader,&dwRead,TRUE))
cout<<"Error in Comm"<<endl;
else
{cout<<"b\n\n";PrintInput(lpBuf,dwRead);}
fWaitingOnRead = FALSE;
break;
case WAIT_TIMEOUT:
cout<<"wait timeout"<<endl;
break;
default:
cout<<"Default Case"<<endl;
break;
}
}
}
dwRead似乎总是设置为1。我将获得驱动器输出的第一个字符(撇号),但其余字符将不读取。我发现了一些解决方法,如果我将其修改为只需要一个字符,然后循环阅读,它将执行。另外,我需要查询驱动器以获取响应,因此在调用此ReadInput函数之前,必须调用WriteBuffer来发送字符。如果我在读写调用之间放置了一个延迟(〜10-50ms),它将读取整个内容。
有人对此有任何想法吗?自从我找到一些解决方法以来,这不是一个大问题,但是在过去的几天里一直困扰着我。
编辑:对Tinman问题的澄清。
您需要使用适当的设置调用SetCommTimeouts
。这是我使用的一些代码。您应该查看COMMTIMEOUTS
结构的MSDN文档。
// Only use read interval timeout. Do not use total read/write timeout.
COMMTIMEOUTS commtimeouts = { min((1000 + GetBaudrate() - 1) / GetBaudrate(), 1), 0, 0, 0, 0 };
SetCommTimeouts(m_hFile, &commtimeouts);
当然,您也可以提供总读取超时而不是间隔超时。
从MSDN:从通信设备读取时,ReadFile
的行为由设置和使用SetCommTimeouts
和GetCommTimeouts
函数检索的当前通信超时确定。如果您无法设置超时值,则可能会发生不可预测的结果。有关通信超时的更多信息,请参见COMMTIMEOUTS
。