none
RS-232 SerialPort - andere Möglichkeit zu warten? RRS feed

  • Frage

  • Hallo Community,

    ich habe ein Problem mit meiner RS-232 Anwendung.

    Diese soll Bytearrays über RS232 verschicken und empfangen.
    Hier meine Anwendung:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO.Ports;
    using System.Threading;
     
    namespace RS232
    {
        class Program
        {
            static int AnzahlGelesenerBytes = 1;
            static SerialPort ep = new SerialPort("COM8", 57600);
            static SerialPort sp = new SerialPort("COM1", 57600);
     
            static byte[] outpuffer = new byte[1024];
     
            static void Main(string[] args)
            {
                byte[] inpuffer = new byte[1024];
     
                ep.DataReceived +=new SerialDataReceivedEventHandler(DataReceivedHandler);
                inpuffer = ByteArrErzeugen(inpuffer);
                oeffnen();
                Senden(inpuffer, sp);
                Warten();
                vergleichen(inpuffer, outpuffer);
                Console.ReadLine();
            }
     
            /// <summary>
            /// Simmuliert einen 1024 Byte großen Bytearray.
            /// </summary>
            /// <param name="inpuffer">Sendepuffer.</param>
            /// <returns>Sendepuffer.</returns>
            public static byte[] ByteArrErzeugen(byte[] inpuffer)
            {
                Random Rande = new Random();
     
                for (int i = 0; i < 1024; i++)
                {
                    inpuffer[i] = Convert.ToByte(Rande.Next(0, 99));
                }
                return inpuffer;
            }
     
            /// <summary>
            /// Oeffnet die COM-Ports
            /// </summary>
            public static void oeffnen() 
            {
                ep.Open();
                sp.Open();
            }
     
            /// <summary>
            /// Sendet 'inpuffer' an den Empfangsport
            /// </summary>
            /// <param name="inpuffer">Sendepuffer</param>
            /// <param name="ep">Empfangsport</param>
            public static void Senden(byte[] inpuffer, SerialPort ep)
            {
                sp.Write(inpuffer, 0, 1024);
            }
     
            /// <summary>
            /// Wartet bis alle Daten angekommen sind
            /// </summary>
            public static void Warten()
            {
                bool fertig = false;
     
                while (fertig == false)
                {
                    if (AnzahlGelesenerBytes == 0)
                    {
                        fertig = true;
                    }
                    else
                    {
                        Thread.Sleep(1);
                    }
     
                    if (!ep.IsOpen)
                    {
                        Console.WriteLine("\nFehler bei der Uebertragung!");
                        Console.ReadLine();
                    }
                }
                AnzahlGelesenerBytes = 1;
            }
     
            /// <summary>
            /// Vergleicht die angekommenen Daten mit den gesendeten Daten.
            /// </summary>
            /// <param name="inpuffer">Sendepuffer.</param>
            /// <param name="outpuffer">Empfangspuffer.</param>
            public static void vergleichen(byte[] inpuffer, byte[] outpuffer)
            {
                bool fehler = false;
                for (int i = 0; i < 1024; i++)
                {
                    if (inpuffer[i] != outpuffer[i])
                    {
                        fehler = true;
                    }
                }
                if (fehler == false)
                {
                    Console.Write("Erfolgreich übertragen.");
                }
            }
     
            /// <summary>
            /// Hört den Empfangspuffer ab bis Daten angekommen sind.
            /// </summary>
            public static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
            {
                //Variable gibt an, an welche Stelle die ausgelesenen Bytes im Puffer geschrieben werden
                int lesestart = 0;
     
                while (AnzahlGelesenerBytes != 0)
                {
                    //versuche die Anzahl der empfangenen Bytes zu ermitteln
                    try
                    {
                        AnzahlGelesenerBytes = ep.Read(outpuffer, lesestart, 1024 - lesestart);
                    }
     
                    //wenn Timeout -> Anzahl = 0
                    catch (TimeoutException)
                    {
                        AnzahlGelesenerBytes = 0;
                    }
     
                    //lege nun die Variable Lesestart neu fest
                    lesestart = lesestart + AnzahlGelesenerBytes;
                }
            }
     
        }
    }

    Nun zu meiner Frage: Gibt es auch noch eine bessere Möglichkeit um zu warten ob alle Daten angekommen sind?

    MFG Phil

    Mittwoch, 24. Oktober 2012 04:22

Antworten

  • Hi xPhil,
    Thread.Sleep mit 1 ms ist keine gute Lösung, da die CPU sehr intensiv belastet wird. Besser ist es z.B. ein AutoResetEvent zu nutzen, welches in der DataReceivedHandler-Methode gesetzt wird, wenn alle Daten angekommen sind. Auf die Auslösung des AutResetEvent kann gewartet werden. Wie das Warten am besten implementiert wird, hängt vom Gesamtkonzept ab. Der Aufrufer arbeitet entweder synchron, asynchron oder mit Ereignisroutine (Endeereignis). Bei synchroner Arbeitsweise wartet die die aufgerufene Methode auf das AutoResetEvent. Bei asynchroner Arbeitsweise wird gestartet und ein Callback mitgegeben, welches für den Aufruf bei Übertragungsende genutzt wird. Für eine Ereignisauslösung ist die Nutzung des SerialPort zu kapseln und das Endeereignis wird entweder in der DataReceivedHandler-Methode ausgelöst oder ein Warten auf das AutoResetEvent löst das Endeereignis aus. In jedem Fall ist mit multithreading zu arbeiten, entweder explizit mit selbst programmierten Befehlen oder implizit mit asynchronen Aufrufen.
     
    --
    Viele Gruesse
    Peter
    Mittwoch, 24. Oktober 2012 05:27

Alle Antworten