سؤال

لدي مشكلة مع دفعة :: ASIO :: قراءة الفئة SERIAL_PORT من جهاز GPS (USB-Serial). توصيل الجهاز والقراءة منه يعمل بشكل جيد، ولكن عندما أقوم بفصل الجهاز وإعادة الاتصال به، لا يقرأ read_some أي بايت من المنفذ.

نظرا لأن Bost لا يتماسك بالكشف عن إرجاع المنفذ التسلسلي (IS_OPEN () صحيحا)، فأنا ألغي بشكل دوري () أو إغلاق () وأفتح (GPS_PORT) الجهاز عندما لا أحصل على البيانات وإعادة تعيين خيارات المنفذ فى الطريق. ولكن هذا لا يساعد أيضا، يبقى المخزن المؤقت للإدخال فارغا.

هل أفتقد شيئا ما، أو القيام بشيء خاطئ، أم أن هذا الخطأ في آسيو؟ هل هناك طريقة قياسية للكشف عن اختفاء المنفذ؟

هل كانت مفيدة؟

المحلول

من الصعب القول ما هو السبب بالضبط في قضيتك، لكن الممارسة تظهر أنك غالبا ما تحتاج إلى تعطيل 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()'جي، وإذا عاد true, ، تدمير مثيل كامل من boost::asio::serial_port وإنشائها مرة أخرى.

نصائح أخرى

عادة يجب أن تحصل على استثناء من النوع boost::system::system_error متي read_some لا يمكن الاستعداد بعد الآن. جرب استخدام read بدلا من ذلك، ربما ترجع خطأ ولا تعود فقط. يمكنك أيضا تجربة طرق ASYNC؛ في هذه الحالة، يجب على المعالج الحصول على كائن خطأ عند قطع الاتصال الجهاز.

إلى أدلة يمكنك الحصول على المقبض إلى المنفذ باستخدام native() وظيفة واستدعاء clearcommerror () على ذلك. قد يعيد الخطأ.

على الرغم من التعامل بسهولة من آسيو 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