繁体   English   中英

无法从串行端口接收数据

[英]Unable to receive data from serial port

目前,我尝试使用VC ++编写串行端口通信,以通过XBee发送器从PC和机器人传输数据。 但是,在我写了一些命令来查询来自机械手的数据之后,我没有从机械手收到任何信息(代码中filesize的输出为0)。 因为我的MATLAB接口有效,所以问题应该发生在代码中,而不是硬件或通讯中。 你能帮我个忙吗?

2014年1月3日更新:我已更新代码。 它仍然无法从我的机器人接收任何数据(读取的输出为0)。 在while循环中使用“ cout <<&read”时,获得“ 0041F01C1”。 我也不知道如何定义缓冲区的大小,因为我不知道要接收的数据大小。 在代码中,我只是给它一个103的随机大小。请帮助我。

// This is the main DLL file.
#include "StdAfx.h"
#include <iostream>

#define WIN32_LEAN_AND_MEAN //for GetCommState command
#include "Windows.h"
#include <WinBase.h>

using namespace std;

int main(){


  char init[]="";

  HANDLE serialHandle;

  // Open serial port
  serialHandle = CreateFile("\\\\.\\COM8", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

// Do some basic settings
  DCB serialParams;
  DWORD read, written;
  serialParams.DCBlength = sizeof(serialParams);

  if((GetCommState(serialHandle, &serialParams)==0))
  {
    printf("Get configuration port has a problem.");
    return FALSE;
   }

   GetCommState(serialHandle, &serialParams);
   serialParams.BaudRate = CBR_57600;
   serialParams.ByteSize = 8;
   serialParams.StopBits = ONESTOPBIT;
   serialParams.Parity = NOPARITY;

   //set flow control="hardware"
   serialParams.fOutX=false;
   serialParams.fInX=false;
   serialParams.fOutxCtsFlow=true;
   serialParams.fOutxDsrFlow=true;
   serialParams.fDsrSensitivity=true;
   serialParams.fRtsControl=RTS_CONTROL_HANDSHAKE;
   serialParams.fDtrControl=DTR_CONTROL_HANDSHAKE;

   if (!SetCommState(serialHandle, &serialParams))
   {
       printf("Set configuration port has a problem.");
       return FALSE;

   }


   GetCommState(serialHandle, &serialParams);

   // Set timeouts
   COMMTIMEOUTS timeout = { 0 };
   timeout.ReadIntervalTimeout = 30;
   timeout.ReadTotalTimeoutConstant = 30;
   timeout.ReadTotalTimeoutMultiplier = 30;
   timeout.WriteTotalTimeoutConstant = 30;
   timeout.WriteTotalTimeoutMultiplier = 30;

   SetCommTimeouts(serialHandle, &timeout);

   if (!SetCommTimeouts(serialHandle, &timeout))
   {
       printf("Set configuration port has a problem.");
       return FALSE;

   }



   //write packet to poll data from robot
   WriteFile(serialHandle,">*>p4",strlen(">*>p4"),&written,NULL);



   //check whether the data can be received
   char buffer[103];



   do {
  ReadFile (serialHandle,buffer,sizeof(buffer),&read,NULL);
      cout << read;
    } while (read!=0);

     //buffer[read]="\0";



   CloseHandle(serialHandle);
   return 0;
}

与串行端口句柄一起使用时,GetFileSize被记录为无效。 使用ReadFile函数接收串行端口数据。

您应该在这里使用strlen而不是sizeof

WriteFile(serialHandle,init,strlen(init),&written,NULL)

创建这样的函数会更好:

function write_to_robot (const char * msg)
{
   DWORD written;
   BOOL ok = WriteFile(serialHandle, msg, strlen(msg), &written, NULL)
      && (written == strlen(msg));
   if (!ok) printf ("Could not send message '%s' to robot\n", msg);
}

但这只是开胃菜。 正如MDN所说,主要的麻烦是:

您不能将GetFileSize函数与非搜索设备(例如管道或通信设备)的句柄一起使用。

如果要从端口读取,则可以简单地使用ReadFile直到它返回零字节。

如果您已经知道机器人响应的最大大小,请尝试阅读那么多字符。 继续读取,直到读取报告的实际字节数小于缓冲区的大小为止。 例如:

#define MAX_ROBOT_ANSWER_LENGTH 1000 /* bytes */
const char * read_robot_response ()
{
    static char buffer[MAX_ROBOT_ANSWER_LENGTH];
    DWORD read;
    if (!ReadFile (serialHandle, buffer, sizeof(buffer), &read, NULL))
    {
        printf ("something wrong with the com port handle");
        exit (-1);
    }
    if (read == sizeof(buffer))
    {
        // the robot response is bigger than it should
        printf ("this robot is overly talkative. Flushing input\n");

        // read the rest of the input so that the next answer will not be
        // polluted by leftovers of the previous one.
        do {
           ReadFile (serialHandle, buffer,  sizeof(buffer), &read, NULL);
        } while (read != 0);

        // report error
        return "error: robot response exceeds maximal length";
    }
    else
    {
        // add a terminator to string in case Mr Robot forgot to provide one
        buffer[read] = '\0';

        printf ("Mr Robot said '%s'\n", buffer);
        return buffer;
    }
}

这个简单的函数返回一个静态变量,每次调用read_robot_response时该变量都会被覆盖。

当然,正确的处理方式是使用阻塞I / O,而不是等待一秒钟并祈祷机器人及时响应,但这将需要更多的精力。

如果您喜欢冒险,可以使用重叠的I / O, 这很详尽的MDN文章对此进行了深入探讨。

编辑:查看您的代码后

// this reads at most 103 bytes of the answer, and does not display them

if (!ReadFile(serialHandle,buffer,sizeof(buffer),&read,NULL))
   {
  printf("Reading data to port has a problem.");
  return FALSE;
    }

// this could display the length of the remaining of the answer,
// provided it is more than 103 bytes long

   do {
  ReadFile (serialHandle,buffer,sizeof(buffer),&read,NULL);
      cout << read;
    }
while (read!=0);

除了收到的前103个字符之外,您什么都没有显示,只是响应的长度。

这应该可以解决问题:

#define BUFFER_LEN 1000
DWORD read;
char buffer [BUFFER_LEN];
do {
    if (!ReadFile(
        serialHandle,  // handle
        buffer,        // where to put your characters
        sizeof(buffer) // max nr of chars to read
             -1,       // leave space for terminator character
        &read, // get the number of bytes actually read
        NULL)) // Yet another blody stupid Microsoft parameter
    {
        // die if something went wrong
        printf("Reading data to port has a problem.");
        return FALSE;
    }

    // add a terminator after last character read,
    // so as to have a null terminated C string to display
    buffer[read] = '\0';

    // display what you actually read
    cout << buffer;
}
while (read!=0);

我建议您将对串行端口访问的实际调用包装在更简单的函数中,这是有原因的。 如前所述,Microsoft接口是一场灾难。 它们冗长,繁琐且仅适度一致。 直接使用它们会导致代码笨拙和混乱。

例如,在这里,您似乎对readbuffer感到困惑

  • 读取保存从串行端口实际读取的字节数
  • 缓冲区保存实际数据。

buffer就是您要显示的内容,以查看机器人回答您的内容

另外,您还应该为机器人准备一份文档,说明您应该期望哪种答案。 了解它们的格式将很有帮助,例如,它们是否为以空字符结尾的字符串。 这样可以省去添加字符串终止符。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM