Невозможно получить данные от последовательного порта

0

В настоящее время я пытаюсь записать связь с последовательным портом в VC++ для передачи данных с ПК и робота через передатчик XBee. Но после того, как я написал несколько команд для опроса данных из робота, я ничего не получил от робота (вывод файла в 0 равен 0). Поскольку мой интерфейс MATLAB работает, так что проблема должна произойти в коде, а не в аппаратном или коммуникационном. Не могли бы вы мне помочь?

01/03/2014 Обновлено: я обновил свои коды. Он по-прежнему не может получать никаких данных от моего робота (вывод read равен 0). Когда я использую "cout << & read" в цикле while, я получаю "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;
}
  • 0
    Работает ли он без XBee, напрямую через последовательный порт?
  • 0
    sizeof (init) будет 0 или 1, если включен NULL. Первый WriteFile () не будет отправлять данные. Это проблема у вас?
Показать ещё 5 комментариев
Теги:
serial-port
robotics

2 ответа

1

GetFileSize документируется недействительным при использовании с дескриптором последовательного порта. Используйте функцию ReadFile для получения данных последовательного порта.

  • 0
    Спасибо за ваш ответ. Не могли бы вы указать мне, как установить размер данных, которые я получу при использовании ReadFile? Например, я могу написать ReadFile (serialHandle, output, sizeof (output), & read, NULL); но я не знаю, как определить размер «вывода». @Scott
  • 0
    Вы должны передать ReadFile размер выходного буфера. Это максимальное количество байтов, которое он вам даст. Но вы не можете установить размер данных, которые вы получите. Это зависит от времени устройства и установленного времени ожидания чтения. Проверьте параметр & read, чтобы узнать, сколько байтов вы фактически получили.
Показать ещё 4 комментария
0

Вы должны использовать 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 с рукоятью nonseeking устройства, такие как трубы или устройство связи.

Если вы хотите читать из порта, вы можете просто использовать 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.

Разумеется, правильным способом делать вещи было бы использование блокирующих входов/выходов, а не ждать одну секунду, и молиться, чтобы робот отвечал вовремя, но для этого потребовалось бы гораздо больше усилий.

Если вы считаете себя предприимчивым, вы можете использовать перекрывающиеся ввода-вывода, поскольку эта статья MDN подробно исследует.

EDIT: посмотрев ваш код

// 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 - это катастрофа. Они многословны, громоздки и только умеренно последовательны. Использование их напрямую приводит к неудобному и запутанному коду.

Здесь, например, вы, похоже, запутались между read и buffer

  • read содержит количество байтов, фактически прочитанных из последовательного порта
  • буфер содержит фактические данные.

buffer - это то, что вы хотите отобразить, чтобы увидеть, что робот ответил вам

Кроме того, у вас должна быть документация для вашего робота, в которой указывается, какие ответы вы должны ожидать. Это поможет узнать, как они отформатированы, например, являются ли они строками с нулевым символом или нет. Это может обойтись без добавления ограничителя строк.

  • 0
    Привет @kuroi, когда я использую буфер [read] = '\ 0'; система выдает мне ошибку «interface_test.cpp (100): ошибка C2440: '=': невозможно преобразовать из« const char [2] »в« char »». Я обновил свои коды в позе. Я думаю, проблема в том, что я не знаю максимальный размер ответа моего робота. Не могли бы вы помочь мне?
  • 0
    Извините, я забыл объявить переменную read . Код был задуман как иллюстрация общего принципа, а не как полностью рабочая программа.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню