【发布时间】:2014-12-06 21:02:28
【问题描述】:
我正在(同步)使用ReadFile() 读取 Windows 中的串行输入,但不是等待串行端口输入然后返回我认为应该的,ReadFile() 而是立即返回值 @ 987654324@ 和 0 的 GetLastError()。(是的,我确定我有正确的错误代码并且没有在两者之间进行系统调用)。
ReadFile() documentation 表示当函数“异步完成时,返回值为零 (FALSE)”。同步读取如何异步完成?为什么这会是一个错误?值得注意的是,读取的数据是垃圾数据,正如人们所预料的那样。
更一般地说,我如何强制 ReadFile() 表现得像一个简单的串行端口同步读取,或者至少表现得像 UNIX read()?
编辑:这是一些源代码:
HANDLE my_connect(char *port_name)
{
DCB dcb;
COMMTIMEOUTS timeouts;
HANDLE hdl = CreateFile(port_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
GetCommState(port_name, &dcb);
dcb.BaudRate = 115200;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.Parity = NOPARITY;
if(SetCommState(hdl, &dcb) == 0)
{
fprintf(stderr, "SetCommState failed with error code %d.\n",
GetLastError());
return (HANDLE) -1;
}
/* TODO: Set a variable timeout. */
timeouts.ReadIntervalTimeout = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 5000; /* wait 5s for input */
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 5000;
if(SetCommTimeouts(hdl, &timeouts) == 0)
{
fprintf(stderr, "SetCommTimeouts failed with error code %d.\n",
GetLastError());
return (HANDLE) -1;
}
return hdl;
}
int my_disconnect(HANDLE hdl)
{
return CloseHandle(hdl);
}
int my_send(HANDLE hdl, char *cmd)
{
DWORD nb = 0;
if(WriteFile(hdl, cmd, strlen(cmd), &nb, NULL) == 0)
{
fprintf(stderr, "WriteFile failed with error code %d.\n",
GetLastError());
return -1;
}
return (int) nb;
}
int my_receive(HANDLE hdl, char *dst, int dstlen)
{
int i;
DWORD r;
BOOL err;
char c = '\0';
for (i = 0; i < dstlen; err = ReadFile(hdl, &c, 1, &r, NULL))
{
if (err == 0)
{
fprintf(stderr, "ReadFile failed with error code %d.\n",
GetLastError());
return -1;
}
if (r > 0)
{
dst[i++] = c;
if (c == '\n') break;
}
}
if (i == dstlen)
{
fprintf(stderr, "Error: read destination buffer not large enough.\
Recommended size: 256B. Your size: %dB.\n", dstlen);
return -1;
}
else
{
dst[i] = '\0'; /* null-terminate the string. */
}
return i;
}
还有我的测试代码:
HANDLE hdl = my_connect("COM4");
char *cmd = "/home\n"; /* basic command */
char reply[256];
my_send(hdl, cmd);
my_receive(hdl, reply, 256);
puts(reply);
【问题讨论】:
-
您能否显示代码以便我们了解您是如何打开串行端口并从中读取数据的?
-
正如本所说,这不应该发生。它可能是由设备驱动程序中的错误引起的,但更有可能是您的代码中的错误。没有看到代码,我们无能为力。
-
感谢您的意见;如果您仍然想看一下,我添加了我的代码。 :)
-
这不是你的真实代码。编译器不会接受
GetCommState(port_name, &dcb);,如果你接受GetCommState(hdl, &dcb);,它就会失败。如果您需要帮助,请至少使用您向我们展示的代码进行一次测试。 -
很抱歉没有回答您关于 STRICT 的问题。它是一个宏,它会导致 Windows 头文件为所有不同类型的句柄创建虚拟结构类型:HANDLE、HWND、HBRUSH、HBITMAP 等,以便它们成为不同且不兼容的指针类型,防止传递错误类型的句柄 (或另一个指针,比如你的
port_name)没有 STRICT 是有效的,它只是typedef void* HANDLE这是任何指针的隐式转换,就像听起来一样危险。
标签: c windows winapi asynchronous serial-port