Frage

Ich habe ein Problem mit der boost :: asio :: serial_port Klasse das Lesen von einem GPS-Gerät (USB-Seriell). Gerät anschließen und das Lesen von es funktioniert gut, aber wenn ich das Gerät trennen und erneut, read_some liest kein Bytes vom Hafen entfernt.

Wie Boost nicht zu erkennen ist Naht dass die serielle Schnittstelle ist weg (istAuf () gibt true), kündige ich in regelmäßigen Abständen (), close () und offen (GPS_PORT), um das Gerät, wenn ich Daten nicht bekommen, Zurücksetzen die Port-Optionen auf dem Weg. Aber auch das nicht helfen, der Eingangspuffer bleibt leer.

Bin ich etwas fehlt oder etwas falsch zu machen, oder ist das ein Fehler in Asio? Gibt es eine standardisierte Möglichkeit zu erkennen, dass die Port weg ist?

War es hilfreich?

Lösung

Es ist schwer zu sagen, was der genaue Grund, in Ihrem Fall ist, aber die Praxis zeigt, dass Sie oft RTS Empfindlichkeit auf Ihrem seriell Port deaktivieren müssen.

RTS ist ein Stift auf reale RS-232 Schnittstelle, die auf, wenn ein Gerät auf der anderen Seite ist, auf.

serial_port::read_some ruft zugrunde liegende Windows API-Funktion, die auf dieses Signal aussieht.

Wie Sie nicht das reale RS-323 Gerät haben, müssen Sie auf der Treiber-Emulation dieses Signals verlassen, die fehlerhaft sein können (und leider oft).

Um sie zu deaktivieren, rufen Sie serial_port::set_option(DCB) mit RTSControl auf RTS_CONTROL_DISABLE.

Ihren Griff Wenn close()'ing nicht hilft, kann es ein Problem mit boost sein. Der Quellcode für close() sieht wie folgt aus:

  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. wenn CloseHandle() aus irgendeinem Grund (oder hängt) ausfällt, der innere Griff Wert beign nicht zugeordnet INVALID_HANDLE_VALUE und is_open() immer true zurück.

Um dies zu umgehen, überprüfen is_open() direkt nach close()'ing, und wenn es true zurückkehrt, zerstören ganze Instanz boost::asio::serial_port und erstellen Sie es erneut.

Andere Tipps

Normalerweise sollten Sie eine Ausnahme vom Typ boost::system::system_error erhalten, wenn read_some kann nicht mehr bereit. Versuchen Sie es mit read statt, vielleicht ist es einen Fehler zurück und kehrt nicht nur. Sie könnten auch die Asynchron-Methoden versuchen; in diesem Fall sollte der Handler einen Fehler Objekt erhalten, wenn das Gerät abgeschaltet wurde.

Alterantively könnten Sie den Griff zum Hafen erhalten die native() Funktion und rufen ClearCommError mit () auf, dass. Es könnte den Fehler zurück.

Trotz der einfachen Handhabung von Asio boost::ip:tcp, denke ich boost serial_port erfordert auf Windows 7.
besondere Vorsicht bei der Handhabung Ich habe ähnliches Problem und überwand er durch eine Instanz von boost::asio::io_service Zurücksetzen , io_service_.reset().
Ich kann Daten asynchron lesen, aber es scheitert elbe aus dem zweiten Versuch zu tun.
In der Tat war es kein Problem mit der Lesefunktion selbst, Registrierung asynchrone Lese gescheitert, die sofortige Rückgabe von boost::asio::io_service::run() in zweitem Versuch führte.

Ich bin nicht sicher, dass dies das gleiche Problem wie ursprüngliches Plakat hatte, weil ich neuere boost Bibliothek dieser Tage verwenden.
Wie auch immer, hier ist meine Lösung:

// 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.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top