Laden...

Ringpuffer einer seriellen Schnittstelle "parallel" zur Anwendungsoberfläche (GUI) auswerten

Erstellt von musicmiles vor 8 Jahren Letzter Beitrag vor 8 Jahren 1.910 Views
M
musicmiles Themenstarter:in
7 Beiträge seit 2015
vor 8 Jahren
Ringpuffer einer seriellen Schnittstelle "parallel" zur Anwendungsoberfläche (GUI) auswerten

Guten Tag myC#-Community,

ich programmiere seid ein paar Jahren verschiedene Mikrocontroller in C. In den Objektorientierten Sprachen habe ich Erfahrungen in C++ und in Java gesammelt, dass liegt aber schon ein paar Jahre zurück.

Nun zum Thema bzw. zu meiner Frage:
Ich habe zur Kommunikation einiger Komponenten (Mikrocontroller) untereinander ein Protokoll entworfen. Dieses Protokoll hat folgenden Aufbau: Befehl, Länge, Daten[n], Checksumme. Sind neue Daten verfügbar, werden diese per Interrupt in einen Ring-Puffer geschrieben und wenn der Prozessor Zeit hat, liest dieser den Ring-Puffer aus und durchläuft Byte für Byte eine Statemaschine und interpretiert diese Daten. Nun möchte ich meine Controller mit einem Programm auf dem Computer kommunizieren lassen und habe dazu eine Forms-Anwendung erstellt. In meine Forms-Anwendung habe ich eine serielle Schnittstelle implementiert und lasse mir, wie auf den Controllern auch, einen Ringpuffer füllen.

Das Füllen des Ringpuffers klappt bisher (testweise) ohne Probleme und wird von dem Ereignis SerialPort.DataReceived folgendermaßen initiert (Code Auszugsweise):


const int MAX_SIZE_REC_QUEUE = 1024;

byte[] ReceiveQueue = new byte[MAX_SIZE_REC_QUEUE];
int RecQueueWrPtr = 0;
int RecQueueRdPtr = 0;
int BytesToRead = 0;

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
	BytesToRead = serialPort1.BytesToRead;
	serialPort1.Read(ReceiveQueue,RecQueueWrPtr,BytesToRead);
	RecQueueWrPtr += BytesToRead;
	if (RecQueueWrPtr >= MAX_SIZE_REC_QUEUE - 1)
		RecQueueWrPtr = 0;
}

Nun möchte ich die Daten in meinem Ringpuffer Byte für Byte einer Statemaschine zuführen und überlege wie ich dies in C# am saubersten gestalte. In dem Event-Handler serialPort1_DataReceived() über eine Schleife Byte für Byte durch den Puffer hangeln scheidet aus. Ich würde das gerne parallel oder besser gesagt pseudoparallel zur GUI machen. Auf meinen Controllern läuft einfach in main() eine Endlosschleife in der die entsprechende Überprüfung bei jedem Durchlauf stattfindet und bei Bedarf bei jedem Durchlauf der entsprechende Handler aufgerufen wird. Aber diese Schleife gibt es ja in meinem C#-Programm nicht.
Bei meiner Suche im Forum bzw. im Internet bin auf Begriffe wie Task, Backgroundworker, Thread, Event und Delegates gestoßen. Allerdings erscheint es mir nicht schlüssig, wie man ein solches Problem Grundsätzlich in C# angeht.
Wer kümmert sich bei einer oben genannten Lösung um den interruptfesten Zugriff auf meinen Ringpuffer, etc..

Kann mir jemand geeignete Lektüre empfehlen oder einen Denkansatz bzgl. des oben genannten Problems geben.

Vielen Dank im voraus

musicmiles

A
764 Beiträge seit 2007
vor 8 Jahren

Hallo musicmiles,

da sonst noch keiner geantwortet hat:

Du hast die richtigen Stichworte schon genannt. Du würdest quasi einen weiteren Thread (Task, Backgroundworker, Thread) anstoßen, der die Verarbeitung des Ringpuffers übernimmt.
Über events und delegates findes die Kommunikation zum Form statt.

Als Einstiegspunkt empfehle ich dir diesen Artikel:
[FAQ] Warum blockiert mein GUI?

Dort findest du entsprechende Links zu weiterführenden Informationen.

Gruß, Alf

M
musicmiles Themenstarter:in
7 Beiträge seit 2015
vor 8 Jahren

Hallo Alf,

vielen Dank für die Antwort. Der Link hat mir sehr geholfen.

Einen schönen Abend

musicmiles

W
872 Beiträge seit 2005
vor 8 Jahren

Die entscheidende Frage hast Du Dir auch gestellt - das GUI wird immer in einem einzigen Thread aktualisiert - daher brauch man immer Control.Invoke/Dispatcher.Invoke zum Aktualisieren...