boost::asio::serial_port чтение после повторного подключения устройства

StackOverflow https://stackoverflow.com/questions/541062

Вопрос

У меня проблема с чтением класса boost::asio::serial_port с устройства GPS (USB-Serial).Подключение устройства и чтение с него работает нормально, но когда я отключаю и снова подключаю устройство, read_some не читает никаких байтов из порта.

Поскольку boost не может обнаружить, что последовательный порт пропал (is_open() возвращает true), я периодически отменяю(), закрываю() и открываю (GPS_PORT) устройство, когда не получаю данные, сбрасывая параметры порта в пути.Но и это не помогает, входной буфер остается пустым.

Я что-то упускаю или делаю что-то не так, или это ошибка в asio?Есть ли стандартный способ обнаружить, что порт пропал?

Это было полезно?

Решение

Трудно сказать, какова точная причина в вашем случае, но практика показывает, что отключать приходится часто. RTS чувствительность вашего последовательного порта.

RTS это настоящая булавка RS-232 интерфейс, который включается, когда включено устройство на другой стороне.

serial_port::read_some вызывает лежащий в основе Windows API функция, которая смотрит на этот сигнал.

Поскольку у тебя нет настоящего RS-323 устройства, вам нужно полагаться на эмуляцию драйвера этого сигнала, который может быть неисправен (и, к сожалению, часто так и есть).

Чтобы отключить его, вызовите serial_port::set_option(DCB) с RTSControl установлен в RTS_CONTROL_DISABLE.

Если close()обращение к вашему дескриптору не помогает, это может быть проблема с boost.Исходный код для close() выглядит так:

  boost::system::error_code close(implementation_type& impl,
      boost::system::error_code& ec)
  {
    if (is_open(impl))
    {
      if (!::CloseHandle(impl.handle_))
      {
        DWORD last_error = ::GetLastError();
        ec = boost::system::error_code(last_error,
            boost::asio::error::get_system_category());
        return ec;
      }

      impl.handle_ = INVALID_HANDLE_VALUE;
      impl.safe_cancellation_thread_id_ = 0;
    }

    ec = boost::system::error_code();
    return ec;
  }

, я.е.если CloseHandle() по какой-то причине происходит сбой (или зависает), значение внутреннего дескриптора не присвоено INVALID_HANDLE_VALUE и is_open() всегда вернусь true.

Чтобы обойти эту проблему, проверьте is_open() сразу после close()'ing, и если он вернется true, уничтожить весь экземпляр boost::asio::serial_port и создайте его снова.

Другие советы

Обычно вы должны получить исключение типа boost::system::system_error когда read_some больше не могу быть готов.Попробуйте использовать read вместо этого, возможно, он возвращает ошибку, а не просто возвращается.Вы также можете попробовать асинхронные методы;в этом случае обработчик должен получить объект ошибки, когда устройство было отключено.

Альтернативно вы можете получить дескриптор порта, используя native() функцию и вызовите для нее ClearCommError().Это может вернуть ошибку.

Несмотря на простоту управления asio boost::ip:tcp, я думаю, улучшение управляемости serial_port требует особой осторожности в Windows 7.
У меня аналогичная проблема и преодолел это, сбросив экземпляр boost::asio::io_service, io_service_.reset().
Я могу читать данные асинхронно, но со второй попытки не получается сделать то же самое.
На самом деле, это не проблема самой функции чтения: регистрация сбоя асинхронного чтения привела к немедленному возврату из boost::asio::io_service::run() со второй попытки.

Я не уверен, что это та же проблема, что и у оригинального постера, потому что в наши дни я использую более новую библиотеку повышения.
В любом случае вот мое решение:

// port open step
port_ = boost::shared_ptr<boost::asio::serial_port>
        (new boost::asio::serial_port(io_service_));
boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service_));
port_->async_read_some(....);
.......

// port close step
port_->cancel();
port_->close();
port_.reset();

io_service_.stop();
io_service_.reset();  // <-- IMPORTANT: this makes serial_port works in repeat use.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top