【发布时间】:2015-03-25 13:21:44
【问题描述】:
我正在尝试使用 windows.h 库通过 RS232 与设备进行通信(SCPI 通信)。我查看了几个关于如何设置的教程和指南,并认为我的代码应该可以正常工作。我可以使用 WriteFile 向设备发送数据。但是,我无法使用 ReadFile 接收任何数据(ReadFile 不会产生错误,但缓冲区大小为 0)。这是我的代码:
#include <stdio.h>
#include <windows.h>
void main ()
{
// CreateFile
HANDLE rs232 = CreateFileA ("\\\\.\\COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if (rs232 == INVALID_HANDLE_VALUE)
{
printf ("fail CreateFile: %d\n", GetLastError ()); system ("pause"); return;
}
// Get & Set CommState
DCB port_configuration;
int err = GetCommState (rs232, &port_configuration);
if (err <= 0)
{
printf ("fail GetCommState: %d\n", GetLastError ()); CloseHandle (rs232); system ("pause"); return;
}
port_configuration.BaudRate = 19200;
port_configuration.ByteSize = 8;
port_configuration.Parity = 0;
port_configuration.StopBits = 0;
port_configuration.DCBlength = sizeof (port_configuration);
err = SetCommState (rs232, &port_configuration);
if (err <= 0)
{
printf ("fail SetCommState\n"); CloseHandle (rs232); system ("pause"); return;
}
// SetCommTimeouts
COMMTIMEOUTS timeout_configuration;
timeout_configuration.ReadIntervalTimeout = 1;// MAXDWORD;
timeout_configuration.ReadTotalTimeoutMultiplier = 1;// 0;
timeout_configuration.ReadTotalTimeoutConstant = 1;// 0;
timeout_configuration.WriteTotalTimeoutMultiplier = 1;// 0;
timeout_configuration.WriteTotalTimeoutConstant = 1;// 0;
err = SetCommTimeouts (rs232, &timeout_configuration);
if (err <= 0)
{
printf ("fail SetCommTimeouts: %d\n", GetLastError ()); CloseHandle (rs232); system ("pause"); return;
}
// WriteFile
DWORD buffer_size_w;
char buffer_w[128] = "*IDN?\n";
err = WriteFile (rs232, buffer_w, strlen (buffer_w), &buffer_size_w, 0);
if (err <= 0)
{
printf ("fail WriteFile: %d\n", GetLastError ()); CloseHandle (rs232); system ("pause"); return;
}
printf ("written %d characters: %s\n", buffer_size_w, buffer_w);
// ReadFile
for (int x = 0; x < 10; ++x)
{
DWORD buffer_size_r;
char buffer_r[128] = {0};
err = ReadFile (rs232, buffer_r, 128, &buffer_size_r, 0);
if (err <= 0)
{
printf ("fail ReadFile: %d\n", GetLastError ()); Sleep (250); continue;
}
printf ("read %d characters: %s\n", buffer_size_r, buffer_r);
Sleep (250);
}
CloseHandle (rs232);
system ("pause");
}
以下是有关我的设置的更多信息:
- 我使用的是 Windows 7 x64 和 Microsoft Visual Studio 2013
- 项目编译为 Win32 控制台
- 我使用 FTDI Chipi-X USB 到 COM 端口转换器电缆
- 我已尝试连接 Newport 运动控制器和 Thorlabs 压电控制器
以下是我迄今为止尝试过的事情:
- 更新 Chipi-X VCOM 的驱动程序
- 将 COMMTIMEOUTS 更改为各种不同的值,如在线指南中所示
- 使用超级终端,我能够与设备完全来回通信。如果我使用自己的程序发送请求设备某些内容的命令,例如“*IDN?\n”,那么我自己的 ReadFile 将不会返回任何内容。但是,当我再次连接超级终端时,我可以按 ENTER 来接收请求的信息。
- 使用 SetupComm() 更改缓冲区大小
- 将 ReadFile 缓冲区大小更改为一次 1 个字节
- 按照本指南中的说明实施 OVERLAPPED 方法:https://msdn.microsoft.com/en-us/library/ff802693.aspx。它给出了与上面的非重叠代码完全相同的问题:windows 函数不会产生错误,但读取缓冲区会保持空。
- 我尝试与不同的设备通信,这很有趣:我再次能够使用超级终端完全来回通信。每当我使用自己的程序发送时,我总是会收到我使用 ReadFile 发回的确切字符串。同样,可以通过重新连接超级终端来检索实际请求的信息。
在我看来,缓冲区有一些问题,但我不知道是什么。我也不确定超级终端是否能够通过不同的 COM 端口连接获取几秒钟前请求的请求信息。可能问题与我的编码有关,因为超级终端工作正常,但如果我将它与我在网上找到的其他代码进行比较,我似乎无法找到我的代码有什么问题。
有人可以帮我吗?
编辑:
- 我使用以下示例创建了一个新的 CLR/C++ 测试应用程序:https://msdn.microsoft.com/en-us/library/system.io.ports.serialport(v=vs.110).aspx。这再次给出了无法接收请求的完全相同的问题。
- 我尝试了 Roline USB 到 RS232 电缆:超级终端可以正常工作,而我的编程却不行。底层硬件或驱动程序可能不是这里的问题。
【问题讨论】:
-
您的超时时间太短了。不要忽略 DCB 中的握手配置。首先让它与另一个程序(如 Putty 或 Hyperterminal)一起工作,这样您就可以确保设备和电缆正常工作。如有必要,请使用 PortMon 等串行端口监控程序来重现完全相同的 DCB。
-
我尝试过更长的超时时间,但它给出了同样的问题。我现在把它们设置得很短,因为我在 for 循环中使用了 ReadFile(它自己的睡眠时间为 250 毫秒)。正如我已经发布的那样,我使用了超级终端并且效果很好。此外,当我使用自己的程序进行连接并使用 GetCommState 时,它应该为我提供与超级终端中使用的完全相同的握手配置。我刚刚尝试了不同的握手配置,但这并没有解决它。我尝试使用 PortMon,但它无法在 Windows 7 x64 上运行,即使更改了兼容模式。
标签: c++ windows serial-port readfile