Laden...

COM-Port Lesen,Schreiben und auf Antwort reagieren

Erstellt von Kalimkaka vor 10 Jahren Letzter Beitrag vor 10 Jahren 5.516 Views
Thema geschlossen
K
Kalimkaka Themenstarter:in
22 Beiträge seit 2014
vor 10 Jahren
COM-Port Lesen,Schreiben und auf Antwort reagieren

Hallo zusammen,

im Bezug auf meinen letzten Post ( Auslesen von ComPort: Wenn ich mich auf den Receiver verbinde, bekomme ich keine Antwort ) habe ich immer noch ein Problem, womit ich jedoch nicht klar komme.

Ich bin nun in der Lage von meinem Receiver (über den ComPort) Daten zu empfangen und zu senden.
Nun probiere ich, Daten zu senden, auf Antwort zu warten und diese Antwort dann weiter zu verarbeiten.

Sprich:

Client sendet zu Gerät (ECHO)
Gerät sendet zu Client (ECHOOK)
Client verarbeitet dieses (ECHOOK)

Leider komm ich nicht weiter, ich hab in meinem Programm auch mal eine Debug - Variable gesetzt und diese mit dem Debugger ausgelesen, leider steht in dieser nur der zuvor abgesendete Befehl.
Habt ihr einen Tipp?

Hier mein Programm:



 public  static void Main(string[] args)
        {

            SerialPort SP = new SerialPort("COM12", 9600, Parity.None, 5, StopBits.One);
            SP.Handshake = Handshake.RequestToSendXOnXOff;
            SP.DataReceived += SP_DataReceived;
            SP.Open();
            Console.ReadLine();
          if(Console.ReadLine()=="Test")
          {
              SP.WriteLine("ECHO");
              if(SP.ReadExisting()=="ECHOOK")
              {
                  //SOllEtwasPassieren
              }
              else
              {

                  //SOllEtwasAnderesPassieren
              }
          }
          SP.Close();
          

        
   }

      static void SP_DataReceived(object sender, SerialDataReceivedEventArgs e)
      {
          SerialPort SerPo = (SerialPort)sender;
          string test = SerPo.ReadExisting();
          Console.Write(test);

      }    

C
2.121 Beiträge seit 2010
vor 10 Jahren

ich hab in meinem Programm auch mal eine Debug - Variable gesetzt

Welche wäre das?

Ich sehe du hast einmal ein Event DataReceived in dem was passiert und dann liest du in der Main Methode nochmal die Daten aus. Du wirst nur an einer Stelle die Antwort bekommen.

Und ganz nebenbei, was ist eigentlich die Frage? Was funktioniert nicht? Was passiert stattdessen?

1.029 Beiträge seit 2010
vor 10 Jahren

Hi,

du fragst aktuell direkt nach dem Senden auf neue Daten ("ECHOOK") ab -
findest du nicht, dass du dem Gerät Zeit zum antworten geben solltest?^^

Die Art der Herangehensweise wird so nicht funktionieren.

An deiner Stelle würde ich eine event-basierte Kommunikationsschicht aufbauen...

Prinzipiell garnicht so schwer - allerdings doch ganz anders, als was du aktuell betreibst 😉

LG

K
Kalimkaka Themenstarter:in
22 Beiträge seit 2014
vor 10 Jahren

Hallo,

danke für die Antwort.

@chilic:
Stimmt meine Frage kommt glaub ich nicht ganz hervor:
Ich probiere, wie gesagt , ein Gerät via RS232 (COMPort) auszulesen.
Das funktioniert auch soweit. Nun sendet das Gerät Befehle zurück, wenn man ihm ein Befehl sendet.
Ich sende ECHO
Gerät sendet ECHOOK
Nun zu meinem Problem. Wenn ich ein ECHO sende bekomm ich kein ECHOOK zurück.
Bei anderem Programmen (z.B. Putty) funktioniert das. Nach einem ECHO sendet Putty ein ECHOOK.

Mein Vorhaben ist im Grunde, dass ich diese Befehle verarbeite.
Sprich, wenn ein ECHOOK vom Gerät kommt, weiß mein Programm, dass der Receiver korrekt hochgefahren.

Lange rede, kurzer Sinn. Ich kann das Gerät auslesen, aber nicht Schreiben, auslesen und erneut Senden.

@Taipi88:

Okay, das seh ich ein. Kannst du mir vielleicht einen Ansatz zeigen? Wie ist dies ggf. machen kann?
Daran verzweifle ich echt. Ich bin froh, dass ich es hinbekommen habe, das Gerät auszulesen, aber Schreiben>Auslesen>Schreiben gleichzeitig bekomm ich nicht hin.

Danke schon mal an Alle und ein schönes Wochenende!
Liebe Grüße

C
2.121 Beiträge seit 2010
vor 10 Jahren

Bei deinem Ablauf ist einiges asynchron, du schreibst dann musst du warten bis wirkklich eine Antwort da ist und so weiter.

Was Taipi88 wahrscheinlich meinte: ReadExisting hört sich an nach: lies das was gerade da ist. Wenn du kurz vorher erst was rausschickst, ist ein paar Mikrosekunden später noch keine Antwort da, also liest du auch keine.
Allerdings sollte dann in deinem Event was ankommen. Sofort nach dem schreiben rufst du Close auf, da ist ein Port also schon zu bevor was ankommen konnte.

Ich würde mir ein sauberes Beispiel suchen und das verstehen. Dann kannst du das an deine Bedürfnisse anpassen.
Einfach mal anhand von Methodennamen drauf los tippen führt zu nichts brauchbarem, da gibt es so viele Fallen in die du sonst tappst. Das verdirbt dir die Laune bevor es funktioniert 😃
In der Hilfe zum SerialPort sollte doch bereits so manches drin stehen. Vor allem wann das Event ausgelöst wird und wie man da am sinnvollsten Daten ausliest und so.

K
Kalimkaka Themenstarter:in
22 Beiträge seit 2014
vor 10 Jahren

Natürlich habe ich im Netz schon gesucht. Leider habe ich dabei nichts passendes gefunden, bzw. das gefundene nicht wirklich verstanden.

Die SerialPort - Klasse zeigt schon einiges auf. Aber leider nur das DataReceived Event.
Und auch kein Beispiel zur parallelen Anwendung (Sprich Schreiben + Lesen), nur wie ich es Lese , mit Hilfe des Events.

Aber recht gebe ich dir. Drauf los zu programmieren, ohne wirklich Ahnung macht nicht wirklich Sinn 😃

185 Beiträge seit 2005
vor 10 Jahren

Vermutlich musst du ein CR oder LF oder CRLF am Ende Senden. Schau doch mal, was da in Putty eingestellt ist.

1.029 Beiträge seit 2010
vor 10 Jahren

Hi,

mit CR/LF hat das wenig zu tun - er kann ja prinzipiell schon vom Gerät lesen...

Wie bereits vermutet wurde ist das DataReceived-Event das richtige Stichwort...

Da der SerialPort bei mir jetzt schon ein wenig was her ist wollte ich mal kurz was bauen - ob's funktioniert: Keine Ahnung - hab nichts mehr zum testen 😦'

Die grundsätzliche Vorgehensweise und vll auch die ein oder andere Falle sollte folgender Code allerdings durchaus darstellen können:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;

namespace WindowsFormsApplication1
{
    public class SerialP : IDisposable
    {
        public event EventHandler<DataEventArgs<string>> MessageReceived;

        SerialPort _SerialPort; // dein serialport

        string _Buffer = String.Empty; // zwischenspeicher für unvollständige daten

        public SerialP()
        {
            _SerialPort = new SerialPort("COM12", 9600, Parity.None, 5, StopBits.One);
            _SerialPort.DataReceived += new SerialDataReceivedEventHandler(_SerialPort_DataReceived);
        }

        public void WriteMessage(string message)
        {
            if (_SerialPort.IsOpen)
                _SerialPort.Write(message);
            else
                throw new Exception("Port is not open.");
        }

        public void Open()
        {
            if (_SerialPort != null && !_SerialPort.IsOpen)
                _SerialPort.Open();
        }

        public void Close()
        {
            if (_SerialPort.IsOpen)
                _SerialPort.Close();
            ((IDisposable)this).Dispose();
        }

        void _SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int length = _SerialPort.BytesToRead;
            char[] str_buffer = new char[length];
            int count = _SerialPort.Read(str_buffer, 0, length);
            string text = new string(str_buffer); // encoding beachten!

            _Buffer += text; // Achtung: Der empfangene "text" ist nicht immer vollständig - deshalb: zwischenspeichern und immer wieder prüfen!

            if (MessageComplete())
            {
                OnMessageReceived(_Buffer); // Event auslösen mit vollständiger Nachricht
                _Buffer = String.Empty; // Zwischenspeichern leeren
            }

            System.Diagnostics.Debug.WriteLine("Data Received: " + text + " [" + count + "]");
        }

        bool MessageComplete()
        {
            // hier überprüfen, ob im Feld _Buffer eine gültige, vollständige Nachricht steht und
            // entsprechenden RÜckgabewert verwenden.
            return true;
        }

        protected void OnMessageReceived(string message)
        {
            if (MessageReceived != null)
                MessageReceived(this, new DataEventArgs<string>(message));
        }

        #region IDisposable

        void IDisposable.Dispose ()
        {
           Dispose(true);
           GC.SuppressFinalize(this);
        }

        ~SerialP()
        {
           Dispose (false);
        }

        protected virtual void Dispose (bool fDisposing)
        {
           if (fDisposing) {
                if (_SerialPort.IsOpen)
                    _SerialPort.Close();
           }
        }

        #endregion
    }

    public class DataEventArgs<T> : EventArgs
    {
        public T Data {get; private set;}

        public DataEventArgs(T data)
        {
            Data = data;
        }
    }
}

Damit solltest du eigentlich alles bewältigen können.

LG

Hinweis von herbivore vor 10 Jahren

So sehe ich das auch. Jedenfalls kann und will das Forum nicht die eigene Einarbeitung in ein neues Themengebiet ersetzen.

Thema geschlossen