我尝试使用WIN32 API写入C ++中的串口,WriteFile不返回ERROR_IO_PENDING但没有任何反应,但是在使用其他程序(在C#中)写入端口之后,c ++程序一直工作,直到我重启Windows 7,这里是写代码:
static DCB dcb = {0};
static HANDLE hComm;
static int _tmain(int argc, _TCHAR* argv[])
{
hComm = CreateFile(
L"\\\\.\\COM3",
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
NULL,
NULL
);
if (hComm == INVALID_HANDLE_VALUE) // error opening port; abort
printf_s("INVALID_HANDLE_VALUE\n");
if (GetCommState(hComm, &dcb))// DCB is ready for use.
{
dcb.BaudRate = CBR_19200; //19200 Baud
dcb.ByteSize = 8; //8 data bits
dcb.Parity = NOPARITY; //no parity
dcb.StopBits = ONESTOPBIT; //1 stop
printf_s("set UP DCB\n");
}
else // Error getting current DCB settings
printf_s("ERROR getting \n"+GetLastError());
osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
WriteABuffer("!serialCMDtoSend\r",sizeof("!serialCMDtoSend\r");
}
static BOOL WriteABuffer(char * lpBuf, DWORD dwToWrite)
{
// Issue write.
if (!WriteFile(hComm, lpBuf, dwToWrite, &dwWritten, &osWrite))
{
if (GetLastError() != ERROR_IO_PENDING) { // WriteFile failed, but it isn't delayed. Report error and abort.
fRes = FALSE;
}
else {
// Write is pending.
if (!GetOverlappedResult(hComm, &osWrite, &dwWritten, TRUE))
fRes = FALSE;
else
fRes = TRUE;// Write operation completed successfully.
}
}
else
fRes = TRUE; // WriteFile completed immediately.
return fRes;
}
任何人都可以看到我的错误吗?
答案 0 :(得分:1)
这是偶然的。您忘记在CreateFile调用中指定FILE_FLAG_OVERLAPPED,因此您永远不会得到重叠的I / O.你可能不知道这个,因为你的错误处理被破坏了,你不知道当GetLastError没有返回ERROR_IO_PENDING时错误代码是什么样的。当WriteFile不必阻塞时,它会偶然工作,因为数据适合驱动程序的传输缓冲区。如本解释的那样,模拟握手设置。
使用重叠I / O并立即调用GetOverlappedResult(TRUE)毫无意义。您也可以使用非重叠I / O,更容易开始。只有在你还有其他有用的东西时才使用它,并且可以调用WaitForMultipleObjects()来检查写入是否完成。在编写的情况下通常很难处理,编写异步代码并不容易。
答案 1 :(得分:0)
有时从干净的DCB开始比使用GetCommState
更好。例如,您没有关闭流量控制,因此行为取决于最后一个程序如何离开它。
您肯定需要正确设置流量控制字段:
fOutxCtsFlow
fOutxDsrFlow
fDtrControl
fDsrSensitivity
fOutX
fInX
fRtsControl
一般情况下,如果您不希望自己的程序依赖于先前的设置,建议不要使用GetCommState
。相反,从零开始:
DCB dcb = { sizeof dcb };
dcb.fBinary = TRUE;
dcb.BaudRate = 19200; //19200 Baud
dcb.ByteSize = 8; //8 data bits
dcb.Parity = NOPARITY; //no parity
dcb.StopBits = ONESTOPBIT; //1 stop
除了您对先前设置的依赖之外,GetCommState
失败了,因为您没有设置DCBlength
(文档清楚地说明这必须由您(来电者)设置。GetCommState
如果没有先检查您提供的尺寸,就无法填写缓冲区。)。