Hallo,
Es gibt hier zwei ältere Threads u.z
GPS - MOUSE - MINI- NAVIGATOR (Assembler) ATmega8
und
SD-Karte Initialisierung Read Write FAT ATmega8 (Assembler), beide von
Bernhard S.
Da ich mir mit Assembler wesentlich leichter tue, versuche ich nun schon
geraume Zeit aus diesen beiden Codes einen GPS-Tracker zu stricken.
Ich kann inzwischen SD-Karten beschreiben und auch über den UART Daten
in das Programm einlesen. Es werden aber immer nur die ersten 3 und das
letzte Byte übernommen. Auf der SD-Karte kommt dabei gar nichts an.
Hat jemand Lust mir auf die Sprünge zu helfen??
Ich weiß natürlich, daß es im Forum eine Reihe von fertigen C-Programmen
dazu gibt, aber ich möchte es ja verstehen.
Gruß Bruno
Hallo Detlev,
vorab danke für die Reaktion!!
Es war mir schon klar, daß ich auf meine Anfrage noch keine konkrete
Hilfe erwarten konnte. Mir reicht aber auch schon die grundsätzliche
Bereitschaft in mein Problem einzusteigen, dann kommen natürlich auch
die etwas umfangreichen Details.
Im Moment geht es um den USART und die Speicherung der empfangenen
Daten.
Der Ablauf ist eigentlich ganz normal, d.h. bei vollem RXC wird ein
Interrupt ausgelöst der auf folgende Routine zeigt:
Der Ablauf ist also, wenn ich es richtig verstanden habe wie folgt:
Bei vollem Empfangspuffer wird der Interrupt ausgelöst und in
"GPS_STRING_EINLESEN" eingelesen. Dann wird geprüft ob es sich um einen
gültigen "$GP..." String handelt und wenn ja wird der ganze String
eingelesen.
Wie funktioniert das aber mit dem Interrupt? Das erste Byte ist OK. Bis
"reti" kann aber doch kein weiterer Interrupt ausgelöst werden. Das
würde aber bedeuten, daß die Einleseroutine komplett durchläuft und mit
"GPS_CLEAR_START" alles wieder auf null gesetzt wird. Damit würde man
aber nie über das erste Byte hinauskommen????
Wo stehe ich da auf der Leitung?
erster "Fehler":
Der ganze "Auswertungsmist" gehört nicht in die Interruptroutine.
Interrupts sind, wie der Name schon sagt, Unterbrechungen des
Hauptprogrammes um irgendwas wichtiges ganz schnell zu erledigen, zB.
ein Byte vom USART abholen.
ok, ist hier nicht so schlimm, weil nur wenig gemacht wird und
tehoretisch viel Zeit zwischen den einzelnen Byte liegt (ca.
1ms@9600Bd).
zweiter echter Fehler:
Du tust nirgendwo dein Statusregister sichern.
Da wird dein Hauptprogramm sicher irgendwann drüber stolpern, wenn
irgend eine Bedingung abgefragt wird, oder irgendwas mit Carry rechnet
wird, und der Interrupt hat mitten drin die Flags verändert.
Absolut doppelplusungut. :)
Wie schnell ist dein ATmega getaktet? Weil, Du hast eventuell nur 2ms
(zwei Byte bei angenommenen 9600Bd) Zeit um dein String im Interrupt
auszuwerten.
>Wie funktioniert das aber mit dem Interrupt? Das erste Byte ist OK. Bis>"reti" kann aber doch kein weiterer Interrupt ausgelöst werden. Das>würde aber bedeuten, daß die Einleseroutine komplett durchläuft und mit>"GPS_CLEAR_START" alles wieder auf null gesetzt wird. Damit würde man>aber nie über das erste Byte hinauskommen????
Wenn ein Byte vom USART abgeholt wurde und kein Fehler auftrat und kein
Endzeichen erkannt wurde, dann wird der Interrupt einfach beendet und es
wird auf das nächste Zeichen gewartet.
Trat ein Fehler auf, wird GPS_CLEAR_START aufgerufen und der Interrupt
verlassen.
Wurde ein Endzeichen erkannt, dann wird der String ausgewertet, dann
GPS_CLEAR_START aufgerufen und zum Schluß der Interrupt verlassen.
Detlef Kunz schrieb:
> erster "Fehler":> Der ganze "Auswertungsmist" gehört nicht in die Interruptroutine.
Da ich diesen Teil des Codes übernommen habe, kann ich nicht genau
sagen, was der Autor bezweckt hat. Ich vermute aber, es geht um
Speicherplatz.
>zweiter echter Fehler:>Du tust nirgendwo dein Statusregister sichern.
Da ich nicht alles zitieren wollte, habe ich diesen Teil unterschlagen.
Komplette Sicherung ist aber vorhanden.
>Wie schnell ist dein ATmega getaktet?
16MHz, Baudrate entsprechend NMEA 4800.
>Wenn ein Byte vom USART abgeholt wurde und kein Fehler auftrat und kein>Endzeichen erkannt wurde, dann wird der Interrupt einfach beendet und es>wird auf das nächste Zeichen gewartet.
Genau das verstehe ich nicht. Wenn die Auswertung beendet ist, kein
Fehler oder Endbyte erkannt wurde, springt er aus
"GPS_STRING_EINLESEN_ENDE" wieder zurück in die "ZEICHEN_EINLESEN"
Schleife, wo aber am Ende der "rcall GPS_CLEAR_START" Befehl sitzt.
Zur Sicherheit hänge ich auch noch diesen gesamten Teil
(GPS_Interrupt.asm) dran.
Bruno M. schrieb:> Genau das verstehe ich nicht. Wenn die Auswertung beendet ist, kein> Fehler oder Endbyte erkannt wurde, springt er aus> "GPS_STRING_EINLESEN_ENDE" wieder zurück in die "ZEICHEN_EINLESEN"> Schleife, wo aber am Ende der "rcall GPS_CLEAR_START" Befehl sitzt.
Wo soll das passieren?
Ich sehe so ein Verhalten nicht im Code.
Hi
Das Ganze wird über die Speicherstelle adr_GPS_DATEN_STRING_KOMPLETT
gesteuert.
Wenn in GPS_STRING_EINLESEN das Ende (ASCII 10) erkannt wird, wird diese
Zelle auf eins gesetzt:
1
GPS_STRING_EINLESEN_ENDE:
2
ldi temp, 10
3
cp GPS_EMPFANGSZEICHEN,temp ; vergleich
4
breq GPS_STRING_EINLESEN_KOMPLETT
5
ret
6
; STRING wurde komplett eingelesen
7
GPS_STRING_EINLESEN_KOMPLETT:
8
ldi temp,1
9
STS (adr_GPS_DATEN_STRING_KOMPLETT),temp ;
10
ret
Die Auswertung erfolgt erst, wenn die Speicherzelle eins ist. Anderen
Falls wird die Interruptroutine ohne Auswertung verlassen.
1
; GPS STRING einlesen
2
rcall GPS_STRING_EINLESEN
3
; IST GPS-STRING komplett ?
4
LDS temp,(adr_GPS_DATEN_STRING_KOMPLETT)
5
tst temp
6
breq ZEICHEN_EINLESEN_FERTIG
7
; AUSWERTUNG der einzelnen STRINGS
8
rcall GPRMC_AUSWERTEN
9
.....
>> Der ganze "Auswertungsmist" gehört nicht in die Interruptroutine.>Da ich diesen Teil des Codes übernommen habe, kann ich nicht genau>sagen, was der Autor bezweckt hat. Ich vermute aber, es geht um>Speicherplatz.
Hat mit Speicherplatz gar nichts zu tun. Die Auswertung kann genau so
gut in der Hauptschleife erfolgen. Das Programm mag zwar funktionieren
aber der Code ist eher suboptimal.
MfG Spess
LDS temp1,(adr_GPS_DATEN_ZEICHEN_ANZAHL) ; aus SRAM einlesen
28
cpi temp1,255 ; vergleich
29
30
brne GPS_STRING_EINLESEN_ENDE ;wenn keine 255 Zeichen, dann springen
31
32
GPS_STRING_EINLESEN_ENDE:
33
ldi temp, 10
34
cp GPS_EMPFANGSZEICHEN,temp ; vergleich
35
breq GPS_STRING_EINLESEN_KOMPLETT
36
37
ret
38
39
.......
Wenn in "GPS_STRING_EINLESEN_ENDE" kein Endzeichen gefunden wird,
springt er mit return wieder in die "ZEICHEN_EINLESEN" Schleife und nach
Auswertung aller Datensätze
rcall GPRMC_AUSWERTEN
rcall GPGGA_AUSWERTEN
rcall GPGSV_X_1
rcall GPGSV_X_2
rcall GPGSV_X_3
; STRING clear
nach
rcall GPS_CLEAR_START
das war der entscheidende Hinweis:
spess53 schrieb:
> Die Auswertung erfolgt erst, wenn die Speicherzelle eins ist. Anderen> Falls wird die Interruptroutine ohne Auswertung verlassen.
Ich hatte es immer genau andersrum interpretiert!
Herzlichen Dank für alle Kommentare!
Gruß Bruno
>Da ich mir mit Assembler wesentlich leichter tue
Ich hatte interpretiert Du kannst AVR-Assembler ;)
So, und warum funktioniert dein Code nun nicht, wenn hier alles ok zu
sein scheint?
> Ich hatte interpretiert Du kannst AVR-Assembler ;)
von "können" bin ich noch meilenweit entfernt, aber zumindest habe ich
damit schon einiges gemacht. Wie du siehst hindert das aber nicht daran
mal richtig auf der Leitung zu stehen.
> So, und warum funktioniert dein Code nun nicht, wenn hier alles ok zu> sein scheint?
Dieser Teil des Codes hat immer funktioniert, aber ich habe ihn nicht
richtig verstanden. Das führt dazu, daß man Probleme manchmal am völlig
falschen Ort sucht. Inzwischen habe ich aber auch den Rest zum Laufen
gebracht, d.h. ich kann vom PC per USART GPS-Signale senden und sie
werden auf der SD-Karte richtig gespeichert.