无法在COM端口上正确使用windows.h ReadFile。 WriteFile似乎工作正常

时间:2015-03-25 13:21:44

标签: c++ windows serial-port readfile

我正在尝试使用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 Motion Controller和Thorlabs压电控制器

以下是我到目前为止所尝试的内容:

  1. 更新Chipi-X VCOM的驱动程序
  2. 将COMMTIMEOUTS更改为各种不同的值,如在线指南
  3. 中所示
  4. 使用超级终端我能够与设备进行完全来回通信。如果我使用自己的程序发送请求某些设备的命令,例如&#34; * IDN?\ n&#34;,那么我自己的ReadFile将不返回任何内容。但是,当我再次连接超级终端时,我可以按ENTER键接收所请求的信息。
  5. 使用SetupComm()
  6. 更改缓冲区大小
  7. 一次将ReadFile缓冲区大小更改为1个字节
  8. 按照本指南中的说明实施OVERLAPPED方法:https://msdn.microsoft.com/en-us/library/ff802693.aspx。它给出了与上面的非重叠代码完全相同的问题:Windows函数不会产生错误,但读取缓冲区将保持为空。
  9. 我尝试与其他设备通信,这很有意思:我再次使用HyperTerminal完全来回沟通。每当我使用自己的程序发送时,我总会收到使用ReadFile发回的确切字符串。并且可以通过重新连接超级终端来检索实际请求的信息。
  10. 在我看来,缓冲区存在一些问题,但我不知道是什么。我也不确定HyperTerminal是否可以通过不同的COM端口连接获取几秒前请求的请求信息。大概这个问题与我的编码有关,因为HyperTerminal工作正常,但如果我把它与我在网上找到的其他代码进行比较,我似乎无法找到我的代码有什么问题。

    有人可以帮助我吗?

    编辑:

    1. 我使用以下示例创建了一个新的CLR / C ++测试应用程序:https://msdn.microsoft.com/en-us/library/system.io.ports.serialport(v=vs.110).aspx。这再次给出了无法接收请求的完全相同的问题。
    2. 我尝试过Roline USB转RS232线缆:HyperTerminal可以正常工作而我的编程没有。底层硬件或驱动程序可能不是问题所在。

1 个答案:

答案 0 :(得分:1)

我解决了这个问题:

我忘了在命令结束时发送回车符(\ r \ n)。显然我用两者测试的设备在实际解析请求之前都在等待组合\ r \ n。 不知何故,通过使用超级终端,我可以将\ r \ n附加到当前的COM端口输出缓冲区,并得到延迟的结果。