Hallo zusammen, ich versuche mit dem MSP430F5438A ein GPS Sensor über UART auszulesen und die empfangenen Daten in ein String zu kopieren um sie dann zu verarbeiten.(NMEA-Standart.. Wobei der Parser der nmealib zu umfangreich wäre) Mir würde es reichen die ersten 100 Zeichen zu speichern. mein Ansatz: char feld[100]; int counter = 0; int i = 0; ..... __interrupt void USCI_A0_ISR(void) { switch (__even_in_range(UCA0IV, 4)) { case 0: break; case 2: while (!(UCA0IFG & UCTXIFG)); { feld[counter] = UCA0RXBUF; if(i <= 20) UCA1TXBUF = feld[i]; else if(i == 20) i = 0; counter++; i++; } break; } Hier tut sich das Problem auf, dass das Feld immer überschrieben wird. Lösung wäre ja ein Dynamisches Array dass die Größe automatisch anpasst je nachdem wie viele Daten aus dem RxBuffer empfangen werden. ich sitze schon seit Tagen an dem Problem und kann es nicht lösen. Bitte um Hilfe
Alex K. schrieb: > ier tut sich das Problem auf, dass das Feld immer überschrieben wird. > Lösung wäre ja ein Dynamisches Array dass die Größe automatisch anpasst > je nachdem wie viele Daten aus dem RxBuffer empfangen werden. Problem erkannt -> gut. Lösungsansatz -> weniger gut. Die Daten werden in Rahmen gesendet. Jeder Rahmen hat einen eindeutigen Anfang und ein eindeutiges Ende. Ein möglicher Ansatz wäre, auf das Startzeichen zu triggern, bis zum Endzeichen zu lesen und dabei die maximale Puffergröße zu überwachen. Dann wird auf einen zweiten Puffer umgeschaltet und die nächsten Daten fließen in den zweiten Puffer, während der erste verarbeitet wird. http://de.wikipedia.org/wiki/Doppelpufferung#Wechselpuffertechnik
Alex K. schrieb: > if(i <= 20) > UCA1TXBUF = feld[i]; Was soll das? Warum sendest Du im Empfangsinterrupt Daten? Und warum nur die ersten 20 Elemente Deines Empfangspuffers? Außerdem überschreibst Du den Speicher nach Deinem Empfangspuffer, da Du "counter" nur erhöhst ... und was geschieht, wenn der den Wert 100 angenommen hat?
Ja wie bereits geschrieben, weiss ich dass der Puffer überschrieben wird. Ich suche ja nach eine Lösung nur bis auf denn Doppelpuffer fällt mir nichts ein. Das verarbeiten des Arrays werde ich aus dem Interrupt auslagern. Kannst du mir nen weiteren Tipp geben? Ich versuche dass jetzt so zu realisieren. Jedes Zeichen was Empfangen wird, wird auf das Startsymbol überprüft und so lange ist das Array geschrieben bis das Endzeichen empfangen wird. In dem Fall ein CR. Dann wird nach dem nächsten Startzeichen gelauscht und dieser wird im zweiten array gespeichert. In der main-methode wird das erste array verarbeitet.
Das erscheint mir nicht der richtige Ansatz zu sein. Ich würde das so umsetzen: Die Empfangsroutine empfängt Bytes und steckt sie in einem Empfangsfifo. Mehr macht sie nicht damit. Das Fifo besteht aus einem Puffer und zwei Zeigern (bzw. Indices), einem Schreib- und einem Lesezeiger. Die Empfangsroutine füllt so lange Daten in den Puffer ein, wie noch Platz im Puffer ist -- ist der Puffer voll, so werden die Daten verworfen. Dazu wird der Schreibzeiger erhöht (und natürlich bei Überschreiten der Pufferobergrenze auf 0 gesetzt). Der Fifofüllstand lässt sich aus Schreib- und Lesezeiger berechnen. In der Main-Routine (oder wo auch immer) werden solange Daten aus dem Fifo geholt und weggeworfen, bis das Startsymbol erkannt wird. Es werden weiterhin Daten aus dem Fifo geholt und damit derweil das Datentelegramm decodiert und wie auch immer ausgewertet. Bei Decodierungsfehlern wird in den Anfangszustand gewechselt, also solange Daten aus dem Fifo geholt und weggeworfen, bis wieder ein Startsymbol erkannt wird.
Rufus Τ. Firefly schrieb: > Die Empfangsroutine füllt so lange Daten in den Puffer ein, wie noch > Platz im Puffer ist -- ist der Puffer voll, so werden die Daten > verworfen. Das scheint mir nicht der richtige Ansatz zu sein. Da du nicht weißt, ab welchem Zeichen im Datenrahmen du empfängst, muss dein Puffer mindestens 2 vollständige Datenrahmen fassen können. Und das für nur einen Datenrahmen. Warum soll man nicht in der ISR auf das Startzeichen triggern? Warum soll man das Rahmenende nicht in der ISR ermitteln? Das Dekodieren wird wesentlich vereinfacht, da immer nur vollständige Rahmen verarbeitet werden. Es dürfte auch Resourcen schonender sein, da der Puffer nicht permanent im Hauptprogramm geparst werden muss: Start-/Endekennung. Und in einem zweiten Puffer wird der nächste Rahmen gespeichert, während der erste ausgewertet wird. Das ist wesentlich effizienter.
Wechelpuffer schrieb: > Da du nicht weißt, ab welchem Zeichen im Datenrahmen du > empfängst, muss dein Puffer mindestens 2 vollständige > Datenrahmen fassen können. Und das für nur einen > Datenrahmen. Nö. Der Empfangs-FIFO selbst kann auch viel kleiner sein als ein Datenrahmen. Wenn für die Decodierung auf den kompletten Datenrahmen zugegriffen werden können muss, muss natürlich der Datenrahmen aufgehoben werden. Aber das erfolgt nicht in der ISR, sondern an der Stelle, wo der Datenrahmen decodiert werden soll. Und da genügt exakt ein Datenrahmen. Entscheidend ist, daß sämtliche Decodierungs- und Auswertungstätigkeit komplett losgelöst vom Empfangspuffer erfolgt. Der Empfangspuffer ist nur dafür da, von der Schnittstelle empfangene Daten solange zu puffern, bis die Auswertungslogik in der Hauptroutine dazu kommt, sie aus dem Empfangspuffer herauszuholen. Wird beispielsweise zum Decodieren mit einem kompletten Abbild des Datenrahmens gearbeitet, so kann die Auswertung erst dann angestoßen werden, wenn das Ende-Zeichen des Datenrahmens empfangen wurde. Jetzt kann der Datenrahmen ausgewertet werden, und die serielle Schnittstelle kann derweil munter weitere Zeichen empfangen. Solange die Dauer der Auswertung nicht länger ist als die Anzahl der Zeichen im Empfangsfifo mal der Bytezeit (bei 9600 Baud ca. 1 msec), geht nichts verloren.
Rufus Τ. Firefly schrieb: > Wird beispielsweise zum Decodieren mit einem kompletten Abbild des > Datenrahmens gearbeitet, so kann die Auswertung erst dann angestoßen > werden, wenn das Ende-Zeichen des Datenrahmens empfangen wurde. Nein, sobald das Starzeichen erkannt wurde, kann es losgehen. Rufus Τ. Firefly schrieb: > Der Empfangs-FIFO selbst kann auch viel kleiner sein als ein > Datenrahmen. Rufus Τ. Firefly schrieb: > Solange die Dauer der > Auswertung nicht länger ist als die Anzahl der Zeichen im Empfangsfifo > mal der Bytezeit (bei 9600 Baud ca. 1 msec), geht nichts verloren. Genau das ist der Haken. Im Hauptprogramm muss peinlichst auf schnelles parsen und verarbeiten geachtet werden. Das ist nicht immer einfach. Displayausgaben und sonstiges machen einem das Leben schwer. Der Baustein hat 16k RAM. Die zweimal 80 Byte für den Wechselpuffer sind zu verschmerzen. Dafür wird die weitere Auswertung unkritisch und einfach. Jetzt gibt es zwei Modelle. Alex kann ja berichten, wenn er es gelöst hat.
Mit fällt es sinnvoller auf das Startzeichen zu Triggern. Wenn ich das Startzeichen habe kopiere ich es in das char Array und kopiere weitere Zeichen solange bis ich das Endzeichen empfangen habe. In der main-Routine erstelle ich ein Abbild des Feldes und bearbeite es. Habe ich den Ansatz soweit richtig nachvollziehen können?
Alex K. schrieb: > Wenn ich das > Startzeichen habe kopiere ich es in das char Array und kopiere weitere > Zeichen solange bis ich das Endzeichen empfangen habe. und überwache die Pufferlänge wegen Speicherüberlauf. Alex K. schrieb: > In der > main-Routine erstelle ich ein Abbild des Feldes nein, nach dem Endezeichen schaltest du auf den zweiten Puffer um. In der Main kann die Auswertung im ersten Puffer direkt nach erkennen des Startzeichens erfolgen.
Es funktioniert soweit, jedoch nicht so wie ich es mir vorstelle. Wie kann ich dem Mikrocontroller mitteilen, dass er bei einer bestimmten Bedingung die restlichen Zeichen aus der Uart verwerfen bzw. ignorieren soll?
Indem Du bei Vorliegen dieser Bedingung weiterhin die Zeichen aus der UART 'rausholst, aber wegwirfst. Das Konzept habe ich beschrieben, aber das wolltest Du Dir mit Deinem Doppelpuffermechanismus ja nicht weiter ansehen.
Hallo Alex K., ich habe mir ebenfalls einmal ein "GPS-Gerät" gebaut, mit Display und allem Schnick und Schnack. Bei mir kommen die NMEA Character im Sekundentakt (schreit also nach zeitlicher Triggerung, um den Anfang zu finden). Die Character wandern in einen zyklischen Puffer mit 256 Byte. Nach Erreichen der Obergrenze fängt man wieder an der untersten Speicherzelle an. Zwei Zeiger wandern durch den Puffer - ein Lese- und ein Schreibzeiger. Sofern beide Zeiger auf die selbe Zelle verweisen liegen keine neuen Daten vor. Die Daten gelangen über einen Interrupt in den Puffer und nach dem Schreiben wird ein Flag gesetzt, dass die Zeiger nicht länger auf die selbe Zelle verweisen. ... usw. Vielleicht habe ich Dir damit einen kleinen Denkanstoss gegeben. Gruß Bernd
Wechelpuffer schrieb: > Im Hauptprogramm muss peinlichst auf schnelles > parsen und verarbeiten geachtet werden. Das ist nicht immer einfach. > Displayausgaben und sonstiges machen einem das Leben schwer. Dann hast du aber in dem restlichen Programm ein paar Designfehler drin wenn da solche Langlaeufer exestieren.
Ich verstehe nicht ganz was mit dem 'Puffer' gemeint ist. Der Buffer des Mc oder das char Feld?
Hallo Alex, sollte die Frage an mich gerichtet sein: Mein Puffer mit z.B. 256 Byte liegt irgendwo im RAM-Bereich, also 256 Speicherzellen. ... beim Bildschirmaufbau auf meinem Display verbrauche ich übrigens auch mehr Zeit, als zwischen zwei Charactern mit 9.600 Baud liegt. Gruß Bernd
Bernd B. schrieb: > ... beim Bildschirmaufbau auf meinem Display verbrauche ich übrigens > auch mehr Zeit, als zwischen zwei Charactern mit 9.600 Baud liegt. Der von mir beschriebene Fifo-Mechanismus verwendet ja auch keinen Fifo von nur einem Zeichen Größe. Ich zitier' mich mal: > Solange die Dauer der Auswertung nicht länger ist als die > Anzahl der Zeichen im Empfangsfifo mal der Bytezeit > (bei 9600 Baud ca. 1 msec), geht nichts verloren. Bei einer Fifogröße von 10 Zeichen stehen also 10 msec zur Verfügung.
Bernd B. schrieb: > ... beim Bildschirmaufbau auf meinem Display verbrauche ich übrigens > auch mehr Zeit, als zwischen zwei Charactern mit 9.600 Baud liegt. Das ist ja auch in dem Fall nicht schlimm solange der Puffer nicht ueberlaeuft. Man sollte allerdings auch keine Ewigkeiten darin verbringen. Der Puffer gleicht sowas ja aus.
Alex K. schrieb: > Wie > kann ich dem Mikrocontroller mitteilen, dass er bei einer bestimmten > Bedingung die restlichen Zeichen aus der Uart verwerfen bzw. ignorieren > soll? Hallo Alex, das geht einfach mit if und einem Dummy Read. Um auf die Startbedingung zu triggern, liest du einfach immer auf Puffer[i] mit i = 0 und zählst beim Speichern der folgenden Byte den Index i hoch. Alex K. schrieb: > Ich verstehe nicht ganz was mit dem 'Puffer' gemeint ist. Puffer ist der Speicher für die zwei Datenrahmen char Puffer[2][120].
Helmut Lenzen schrieb: > Dann hast du aber in dem restlichen Programm ein paar Designfehler drin > wenn da solche Langlaeufer exestieren. Das sehe ich anders. Das Hauptprogramm ist völlig zeitunkritisch. Der µC kann auch in den Low Power Mode verzweigen und sich ausschlafen. Zeitkritische Dinge werden per Interrupt bedient.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.