Pregunta

Tengo un problema con el impulso :: la clase de lectura asio :: serial_port desde un dispositivo GPS (USB-Serial). Conexión del dispositivo y la lectura desde que trabaja muy bien, pero cuando desconectar y reconectar el dispositivo, read_some no ha leído ninguna bytes desde el puerto.

Como impulso no costura para detectar que el puerto serie se ha ido (is_open () devuelve verdadero), puedo cancelar periódicamente (), close () y abierto (GPS_PORT) del dispositivo cuando no tengo los datos, restablecer las opciones de puerto en el camino. Pero esto no ayuda tampoco, el buffer de entrada se queda vacía.

Me estoy perdiendo algo, o haciendo algo mal, o se trata de un error en asio? ¿Hay una manera estándar para detectar que el puerto se ha ido?

¿Fue útil?

Solución

Es difícil decir cuál es la razón exacta en su caso, pero la práctica demuestra que a menudo es necesario desactivar la sensibilidad RTS en su puerto serie.

RTS es un pasador en la interfaz de bienes RS-232 que está en cuando un dispositivo en el otro lado está encendido.

serial_port::read_some invoca la función Windows API subyacente que se ve en esta señal.

A medida que usted no tiene el dispositivo RS-323 verdadera, es necesario confiar en la emulación de controlador de esta señal, que puede estar defectuoso (y por desgracia a menudo es).

Para desactivarlo, invocar serial_port::set_option(DCB) con RTSControl establecido en RTS_CONTROL_DISABLE.

Si close()'ing el mango no ayuda, puede ser un problema con boost. El código fuente para close() se ve así:

  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;
  }

, i. mi. Si CloseHandle() falla por alguna razón (o bloquea), el valor de la manija interna no está asignado a beign INVALID_HANDLE_VALUE y is_open() siempre devolverá true.

Para evitar esto, compruebe is_open() justo después close()'ing, y si devuelve true, destruir toda instancia de boost::asio::serial_port y crear de nuevo.

Otros consejos

Normalmente debería hacerse una excepción de tipo boost::system::system_error cuando read_some no pueden listo ya. Trate de usar read lugar, tal vez devuelve un error y no se limita a volver. También puede probar los métodos asincrónicos; en este caso el controlador debe recibir un objeto de error cuando se desconectó el dispositivo.

Alterantively podría obtener el identificador para el puerto usando la función native() y llame ClearCommError () en eso. Se podría devolver el error.

A pesar de la facilidad de manejo de boost::ip:tcp asio, creo que el manejo de impulso serial_port requiere precaución especial en Windows 7.
Tengo un problema similar y lo superó restableciendo una instancia de boost::asio::io_service , io_service_.reset().
Soy capaz de leer los datos de forma asíncrona pero deja de hacer lo mismo en el segundo intento.
De hecho, no hubo ningún problema por sí misma función de lectura, su registro de lectura asíncrona no, lo que llevó retorno inmediato de boost::asio::io_service::run() en el segundo intento.

No estoy seguro de que este es el mismo problema que el cartel original tenía porque estoy utilizando más reciente biblioteca de impulso de estos días.
De todos modos aquí está mi solución:

// 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.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top