2016-06-02 9 views
2

Ich arbeite mit dem Tiva Launchpad EK-TM4C123GXL und dem ESP8266 WIFI Modul.Wie wird eine Funktion entworfen, die angibt, wann "+ IPD" vom UART ankommt?

Wenn dieses Modul ein WLAN-Paket erhält, sendet es es über den UART-Port an den Mikrocontroller.

Die durch Esp8266 verwendete Format eines Pakets (zum uC via UART) zu senden ist:

+IPD,n:xxxxx\r\nOK\r\n

wobei:

  • n die Länge (in Bytes) der Daten Paket
  • : zeigt an, dass das nächste Byte das erste Datenbyte
  • sein wirdist das Datenpaket
  • \r\nOK\r\n sind 6 Bytes und sie sind nutzlos für mich.

Zum Beispiel:

+IPD,5:hello\r\nOK\r\n

Hier ist meine Situation:

ich auf einem bestehenden Projekt gerade arbeite, wo ich diese beiden Dinge nicht ändern:

1- Das UART-Modul ist bereits so konfiguriert, dass es einen Interrupt generiert, wenn sein Empfangs-FIFO (16 Byte) halb voll ist.

2- Die ISR (Interrupt Service Routine), die diesen Interrupt behandelt:

  • liest nur ein Byte aus dem UARTDR (UART-Datenregister)

  • speichert sie in eine Variable

  • ruft eine Funktion auf (genannt rx_data()), die dieses Byte behandelt.

Jetzt habe ich diese Funktion schreiben, die so genannte RX_DATA(), in C-Sprache.

So wird die Meldung Form der Esp8266 Modul kommt an diese Funktion übergeben wird, RX_DATA(), ein Byte zu einem Zeitpunkt, und diese Funktion muss in der Lage sein den Header

  • identifizieren +IPD,

  • lesen die Länge n des Datenpakets

  • Speichern des Datenpakets xxxxx (das ist lokalisieren d nach dem : Charakter und vor den ersten \r Zeichen) in einen Puffer

  • das letzte Byte verwerfen \r\nOK\r\n (diese 6 Bytes sind nutzlos für mich, aber, wie auch immer, ich sie sie aus dem Empfangs-FIFO zu entfernen lesen muß)

denke ich Schritt arbeitet für Schritt, so dass ich jetzt bin Argumentation auf:

wie die +IPD, zu identifizieren, wenn man bedenkt, dass nur ein Byte zu einem Zeitpunkt wird an diese Funktion übergeben?

+1

Speichern Sie den Status an einem Ort, der beim Verlassen der Funktion nicht gelöscht wird. – MikeCAT

+0

Sie könnten einen globalen RX-Puffer zum Speichern der Bytes erstellen, und jedes Mal, wenn 'rx_data' aufgerufen wird, wird das Byte zum Puffer hinzugefügt und der Index (auch eine globale Variable) wird inkrementiert. Führen Sie dies aus, bis Sie eine vollständige Nachricht erhalten haben oder bis Sie die gewünschten Daten sehen/haben und löschen Sie den Puffer und setzen Sie den Index zurück, um erneut zu starten. – DigitalNinja

Antwort

2

Es ist Zeit, eine Zustandsmaschine zu machen. Jedes Mal, wenn rx_data aufgerufen wird, würden Sie den Status Ihrer Statusmaschine aktualisieren, und irgendwann werden Sie wissen, dass Sie die Zeichenfolge "+ IPD" erhalten haben.

Die einfachste Sache, die so etwas wie dies wäre funktionieren könnte, unter der Annahme, dass das Byte aus dem UART empfangenen als Argument an rx_data geben wird:

void rx_data(uint8_t byte) 
{ 
    static uint8_t state = 0; 
    if (byte == '+') { state = 1; } 
    else if (state == 1 && byte == 'I') { state = 2; } 
    else if (state == 2 && byte == 'P') { state = 3; } 
    else if (state == 3 && byte == 'D') { state = 4; } 
    else if (state == 4 && byte == ',') { 
     state = 0; 
     handleIPDMessage(); // we received "+IPD," 
    } 
    else { state = 0; } 
} 

Sie können sehen, dass handleIPDMessage(), wenn und nur aufgerufen, wenn die letzten empfangenen Zeichen waren "+ IPD".

Sie sollten jedoch überlegen, eine allgemeinere Zustandsmaschine zu schreiben, die mit Zeilen arbeitet, anstatt nur nach dieser einen Zeichenfolge zu suchen. Das wäre wahrscheinlich einfacher zu schreiben und robuster. Wenn eine vollständige Zeile empfangen wird, würden Sie eine Funktion namens handleLineReceived() aufrufen, um diese Zeile zu behandeln. Diese Funktion hätte Zugriff auf einen Puffer mit der gesamten Zeile und könnte es auf beliebige Weise parsen. (Sei nur vorsichtig, dass du nie über das Ende dieses Puffers hinaus schreibst.)

Übrigens würde ich Logik nicht so in eine ISR einfügen. Es ist im Allgemeinen am besten, ISRs einfach und schnell zu halten. Wenn Sie dies noch nicht tun, speichern Sie das Byte in einem Ringpuffer in der ISR und lesen Sie dann aus dem Ringpuffer in Ihrer Hauptschleife, und jedes Mal, wenn Sie ein Byte aus dem Ringspeicher lesen, rufen Sie dann eine Funktion wie die beschriebene rx_data Funktion auf oben, um das Byte zu verarbeiten.

+0

Danke für Ihre Antwort, große Antwort! Es ist was ich gesucht habe! Wie ich in meinem ersten Post gesagt habe, arbeite ich an einem bestehenden Projekt, also sollte ich die (bereits) existierende ISR nicht ändern. Aber ich habe viel von Ihrer Antwort gelernt, und jetzt weiß ich auch, dass es bessere Möglichkeiten gibt, mit meinem Problem umzugehen.Sobald ich das "up vote privilege" erreicht habe, gebe ich Ihnen die Stimme, die Sie verdienen. – rainbow