ما الذي يمكن أن يؤثر على القيم التي يتم إرجاعها بواسطة Serialport.Read()

StackOverflow https://stackoverflow.com/questions/117945

  •  02-07-2019
  •  | 
  •  

سؤال

لقد قمت بكتابة تطبيق بسيط في C# 2.0 باستخدام فئة .Net Framework 2.0 Serialport للتواصل مع بطاقة وحدة التحكم عبر COM1.

حدثت مشكلة مؤخرًا حيث كانت وحدات البايت التي تم إرجاعها بواسطة أسلوب القراءة غير صحيحة.لقد أعاد المقدار الصحيح من البايتات، لكن القيم فقط كانت غير صحيحة.بالرغم من ذلك، لا يزال هناك تطبيق مشابه مكتوب بلغة دلفي يُرجع القيم الصحيحة.

إستعملت بورتمون لتسجيل النشاط على المنفذ التسلسلي لكلا التطبيقين، قارنت السجلين وهناك توجد بعض الإعدادات المختلفة البسيطة (على ما يبدو) وحاولت تقليد تطبيق دلفي بأكبر قدر ممكن، ولكن دون جدوى.

إذًا، ما الذي يمكن أن يؤثر على قيم البايت التي يتم إرجاعها بواسطة طريقة القراءة؟

معظم الإعدادات بين التطبيقين متطابقة.

فيما يلي قائمة بالخطوط التي اختلفت في سجل Portmon:

تطبيق دلفي :

IOCTL_SERIAL_SET_CHAR المسلسل 0 النجاح إي أو إف: تيار مستمرخطأ:0 برك:0 اي في تي:0 اكسون:11 اكسوف:13
IOCTL_SERIAL_SET_HANDFLOW SERIAL0 SUCKING SUCK: 0 استبدال: 0 حد اكسون: 256 حد Xoff: 256 IOCTL_SERIAL_SET_TIMEOUTS Serial0 SUCCESS RI:-1 رينجيت ماليزي: 100 أرسي: 1000 وم: 100 WC:1000 IOCTL_SERIAL_SET_WAIT_MASK Serial0 قناع النجاح:ركسشار ركسفلاغ فارغ CTS DSR RLSD BRK خفيفة RX80FULL

تطبيق سي#:

IOCTL_SERIAL_SET_CHAR المسلسل 0 النجاح EOF: 1 أخطأ:0 برك:0 اي في تي: 1 أ xon: 11 xoff: 13 IOCTL_SERIAL_SET_HANDFLOW SERIAL0 النجاح الهز: 0 استبدال: 0 حد اكسون:1024 حد Xoff: 1024 IOCTL_SERIAL_SET_TIMEOUTS Serial0 SUCCESS RI:-1 جمهورية مقدونيا:-1 أرسي: 1000 وم:0 WC:1000 IOCTL_SERIAL_SET_WAIT_MASK Serial0 قناع النجاح:Rxchar Rxflag CTS DSR RLSD BRK خفيفة

تحديث:

البايتات الصحيحة التي تم إرجاعها كانت:91، 1، 1، 3، 48، 48، 50، 69، 66، 51، 70، 55، 52، 93 (14 بايت).القيمة الأخيرة هي المجموع الاختباري البسيط.

القيم غير الصحيحة التي تم إرجاعها كانت:91، 241، 254، 252، 242، 146، 42، 201، 51، 70، 55، 52، 93 (13 بايت).

كما ترون فإن البايتات الخمس الأولى والأخيرة التي تم إرجاعها تتوافق.

يشير الحدث ErrorReceived إلى حدوث خطأ في الإطار، وهو ما قد يفسر القيم غير الصحيحة.لكن السؤال هو لماذا يواجه SerialPort خطأً في الإطارات بينما يبدو أن تطبيق Delphi لا يواجه خطأً؟

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

المحلول

حسنًا، يبدو كما لو أن المشكلة قد تم حلها (على الأقل في الوقت الحالي).

من الواضح أن خطأ في الإطارات تسبب في إرجاع قيم غير صحيحة.لقد كتبت تطبيق VB6، باستخدام عنصر التحكم MSComm، والذي كان يعمل بشكل جيد، وقمت بمقارنة ملفات السجل التي تم إنشاؤها بواسطة Portmon.

التقطت الاختلافات التالية

تطبيق VB6 :

IOCTL_SERIAL_SET_HANDFLOW SERIAL0 النجاح يهز:1 استبدال: 0 xonlimit: 256 xofflimit: 256

تطبيق سي#:

IOCTL_SERIAL_SET_HANDFLOW SERIAL0 النجاح يهز:0 استبدال: 0 xonlimit: 1024 xofflimit: 1024

من خلال اللعب بالإعدادات وجدت أنه إذا قمت بتعيينها_serialPort.DtrEnable = trueيقوم تطبيق C# بإنشاء إدخال السجل التالي:

IOCTL_SERIAL_SET_HANDFLOW SERIAL0 النجاح يهز:1 استبدال: 0 xonlimit: 1024 xofflimit: 1024

يبدو أن هذا يمنع حدوث خطأ في الإطارات ويبدو أن التطبيق يعمل بشكل جيد.

نصائح أخرى

هل قمت بفحص الإعدادات الخاصة بعدد بتات البيانات وبتات التوقف والتكافؤ؟

بت التكافؤ هو نوع من آلية اكتشاف الأخطاء.على سبيل المثال:إذا قمت بالإرسال باستخدام 7 بتات بيانات وبتة تماثل واحدة، فسيتم استخدام البت الثامن لاكتشاف أخطاء انعكاس البت.إذا كان المتلقي يتوقع 8 بتات بيانات ولا توجد بتات تكافؤ، فستكون النتيجة مشوهة.

لسوء الحظ، لم تذكر بالضبط نوع الاختلافات التي تحصل عليها.هل هي شخصية عرضية مختلفة أم أن جميع بياناتك الواردة مشوهة؟لاحظ أن الأحرف التي تتم قراءتها من خلال وظيفة SerialPort.Read يمكن تغييرها بواسطة النظام بسبب إعداد SerialPort.Encoding ملكية.يؤثر هذا الإعداد على تفسير النص الوارد كما لو كان نصًا بتنسيق ASCII أو Unicode أو UTF8 أو أي نظام ترميز آخر يستخدمه Windows لتحويل "البايت (البايتات) الخام" إلى "نص قابل للقراءة".

إذا كنت تقرأ في مصفوفة بايت (على سبيل المثال:SerialPort.Read) يجب أن تحصل بالضبط على وحدات البايت التي تراها على PortMon.

إذا كنت تقوم بالتحويل إلى أحرف (SerialPort.ReadLine أو SerialPort.ReadChar)، فسيتم تشفير البيانات باستخدام التشفير الحالي (خاصية SerialPort.Encoding)، وهو ما يوضح الاختلافات التي تراها.

إذا كنت تريد رؤية الأحرف بنفس القيم الثنائية مثل البايتات الموجودة على السلك، فإن التشفير الجيد الذي يجب استخدامه هو Latin-1 كما هو موضح في هذا المشنور.

مثال:

SerialPort.Encoding = Encoding.GetEncoding("Latin1")
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top