Domanda

Ho un problema con il boost :: classe lettura asio :: porta seriale da un dispositivo GPS (USB-Seriale). Collegare il dispositivo e la lettura da esso funziona bene, ma quando scollegare e ricollegare il dispositivo, read_some non legge byte dalla porta.

Come spinta non cucitura a rilevare che la porta seriale è andato (is_open () restituisce true), ho periodicamente annullare (), close () e aperto (GPS_PORT) il dispositivo quando non ho ricevuto i dati, il ripristino le opzioni di porta sulla strada. Ma questo non aiuta, il buffer di ingresso rimane vuoto.

Mi manca qualcosa, o fare qualcosa di sbagliato, o si tratta di un bug in ASIO? C'è un modo standard per rilevare che la porta è andato?

È stato utile?

Soluzione

E 'difficile dire quale sia la ragione esatta nel tuo caso, ma la pratica dimostra che spesso è necessario disattivare la sensibilità RTS sulla vostra porta seriale.

RTS è un perno sull'interfaccia reale RS-232 che è acceso quando un dispositivo sull'altro lato è acceso.

serial_port::read_some invoca la funzione Windows API di fondo che appare su questo segnale.

Per quanto non si dispone il dispositivo RS-323 vero e proprio, è necessario fare affidamento su l'emulazione del driver di questo segnale, che potrebbe essere difettosa (e purtroppo spesso è).

Per disabilitarlo, invocano serial_port::set_option(DCB) con RTSControl impostato RTS_CONTROL_DISABLE.

Se il vostro close()'ing maniglia non aiuta, può essere un problema con boost. Il codice sorgente per close() assomiglia a questo:

  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. e. se CloseHandle() riesce per qualche motivo (o si blocca), il valore di handle interno non è assegnato a beign INVALID_HANDLE_VALUE e is_open() restituirà sempre true.

Per risolvere questo, controllare is_open() subito dopo close()'ing, e se restituisce true, distruggere tutta istanza di boost::asio::serial_port e creare di nuovo.

Altri suggerimenti

Normalmente si dovrebbe ottenere un'eccezione di tipo boost::system::system_error quando read_some non può pronta più. Provate ad usare read invece, forse restituisce un errore e non si limita a tornare. Si potrebbe anche provare i metodi asincroni; in questo caso il gestore dovrebbe ottenere un oggetto errore quando il dispositivo è stato disconnesso.

Alterantively si potrebbe ottenere la maniglia alla porta usando la funzione native() e chiamare ClearCommError () su questo. Potrebbe restituire l'errore.

Nonostante la maneggevolezza di boost::ip:tcp ASIO, penso che la manipolazione spinta serial_port richiede particolare cautela su Windows 7.
Ho avuto problemi simili e ha ottenuto su di esso reimpostando un'istanza di boost::asio::io_service , io_service_.reset().
Posso leggere i dati in modo asincrono ma non riesce a fare stessa cosa dal secondo tentativo.
In realtà, non era un problema di funzione di lettura per sé, registrando lettura asincrono fallito, che ha portato ritorno immediato da boost::asio::io_service::run() nel secondo tentativo.

Non sono sicuro che questo è lo stesso problema come poster originale aveva perché sto usando più recente libreria Boost di questi giorni.
Comunque qui è la mia soluzione:

// 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.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top