دفعة :: ASIO :: Serial_Port القراءة بعد إعادة الاتصال
-
22-08-2019 - |
سؤال
لدي مشكلة مع دفعة :: 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.