Hallo,
ich empfange Daten von einem GPS Modul, das Programm in Bascom sieht
gekürzt so aus:
...
Config Serialin1 = Buffered , Size = 20 , Bytematch = 13
...
do
print incoming_data
waut 2
loop
...
sub Serial1charmatch:
input incoming_data noecho
Return
end sub
Sprich wenn ein \r erkannt wird, werden die ankommenden Daten in eine
Variable geschrieben und im Hauptprogramm ausgegeben.
Die gesendeten Strings vom Sensor sehen ja pro Durchlauf in etwa so aus:
$GPRMC,191410,A,4735.5634,N,00739.3538,E,0.0,0.0,181102,0.4,E,A*19
$GPRMB,A,9.99,L,,Exit,4726.8323,N,00820.4822,E,29.212,107.2,,V,A*69
$GPGGA,191410,4735.5634,N,00739.3538,E,1,04,4.4,351.5,M,48.0,M,,*45
$GPGSA,A,3,,,,15,17,18,23,,,,,,4.7,4.4,1.5*3F
$GPGSV,2,1,08,02,59,282,00,03,42,287,00,06,16,094,00,15,80,090,48*79
$GPGLL,4735.5634,N,00739.3538,E,191410,A,A*4A
$GPBOD,221.9,T,221.5,M,Exit,*6B
Mein Problem ist nun, dass ich immer nur die erste Zeile, also den
$GPRMC Teil bekomme, da jede Zeile per \r abgeschlossen wird. Ich
benötige aber den $GPGGA Teil.
Könnte mir jemand einen Tipp geben, wie ich den Code abändern muss?
Danke!
Das ist nur ein Beispiel, ich habe es aus dem Kopf getippt. Tatsächlich
steht da meintwegen 200. Trotzdem ist nur die komplette erste Zeile
verfügbar - die würde in die 20 Zeichen auch nicht passen. Das sind
nämlich ca 69 Zeichen.
Alex schrieb:
> Das ist nur ein Beispiel, ich habe es aus dem Kopf getippt.
Dann bin ich raus
Ich habe es nämlich satt, Fehler in Code zu suchen, der nicht dem
entspricht, der tatsächlich auf dem AVR läuft und der dann auch nur aus
ein paar nichtssagend hingerotzten Zeilen besteht.
Du sitzt vor dem Programm, hast es laufen und findest den Fehler nicht.
Und wir sollen hier aus ein paar Bruchstücken erraten, was da wieder mal
schief läuft.
Der Vorlage angemessen auch mal so nichtssagend hingerotzt:
Alle Zeilen wegschmeissen, bis die richtige da ist.
Das ist aber nun wirklich Programmieren erstes Kapitel und zeigt
anschaulich was passiert, wenn ein Anfaenger einfach
drauflosprogrammiert, ohne sich vorher Gedanken zu machen.
Gast
Hallo,
Du detektierts halt "$GPGGA" und verarbeitest dann erst weiter...
Die überlegng hat mit "programmieren" erst einmal noch nichts zu tun,
sondern nur mit etwas Nachdenken.
Entweder Du postest hier den gesamten Code und alle Unmstände oder Du
läßt es besser sein.
Man will Dir ggf. helfen, aber nicht verarscht werden, alles klar ?!
DS
Hier das Programm
$regfile = "m644pdef.dat"
$crystal = 16000000
$baud = 9600
$baud1 = 9600
Declare Sub Serial0charmatch()
Config Serialin = Buffered , Size = 200 , Bytematch = 13
Dim Incoming_data As String * 200
Dim Filtered As String * 200
Dim Writestring As String * 20
Dim Length As Integer
Dim Var As Integer
'Hauptschleife
Waitms 500
Dim A As Word , B As Word
Dim Einzelzeichen As String * 1
Enable Interrupts
Do
If Var = 1 Then
Disable Interrupts
Length = Len(incoming_data) - 1
Filtered = Mid(incoming_data , 2 , Length)
print Filtered
Enable Interrupts
Var = 0
End If
Wait 2
Loop
End
'Daten vom Buffer auslesen
Sub Serial0charmatch()
Incoming_data = ""
Input Incoming_data Noecho
Var = 1
Return
End Sub
schau Dir mal hier das 2. Beispiel mit den Overlays an und lies Dir mal
durch was der sachkundige Autor schreibt. Das ist sehr strukturiert und
wäre eine gute und bessere Ausgangsbasis für einen funktionierenden
Code..
http://www.rowalt.de/mc/index.htm
......
Wer das Vorgehen String=String+Zeichen nicht mag, kann mit einem kleinen
Trick optimal vorgehen: In Bascom ist es möglich, ein und denselben
SRAM-Platz mit mehreren Variablen zu belegen. Wir können z.B. anweisen,
daß unsere String-Variable auf Adresse &H60 gesetzt werden soll.
Gleichzeitig können wir ein Feld mit 11 Bytes dimensionieren, das auf
der gleichen Adresse liegen soll (ein 10 Byte langer String benötigt 11
Bytes Platz). Damit können wir ganz einfach und effizient über völlig
verschiedene Methoden auf denselben Speicher zugreifen. Schauen Sie sich
bitte das folgende Listing an. '0011.BAS: Optimierter String-Empfang
$Regfile = "2313def.dat"
$Crystal = 3686400
$Baud = 9600
Dim s As String*10 At &H60
Dim b(11) As Byte At &H60 Overlay
Dim n As Byte
On URXC OnRxD
Enable URXC
Enable Interrupts
Main:
If n > 9 Then
Print s
n = 0
End If
Goto Main
OnRxD:
Incr n
b(n) = UDR
Return
Der String wird auf Adresse &H60 im AVR abgelegt. Dies ist die Adresse
des ersten Bytes im SRAM (da der AT90S2313 über 128 Bytes SRAM vefügt,
ist die höchste SRAM-Adresse &HDF). Quasi "darüber", also auf die selbe
Adresse, legen wir ein Feld, das genauso lang wie der String ist. Das
ist alles. Der Trick ist nur, daß wir beim Füllen des Strings in unserem
Anwendungsfall am effizientesten mit einem Feld arbeiten können, während
in anderen Fällen die Arbeit mit einem String günstiger sein kann.
Welche Wege man in der Praxis gehen will, hängt natürlich immer von der
Anwendung ab. Die Anwendung des Overlay-Tricks kostet weder zusätzlichen
Code, noch SRAM. Es ist vielleicht eher wie die Auswahl zwischen
Buddelschippe, Schaufel und Bagger bei ein und dem selben Haufen Sand.
Und noch ein drittes UART-Mißverständnis trat wiederholt auf: Der
UART-Empfangs-Interrupt meldet, daß ein Zeichen empfangen wurde. In der
Interrupt-Routine kann man deshalb auch immer nur ein Zeichen auslesen.
Zum Beispiel macht es daher keinen Sinn, in der Interrupt-Routine den
Bascom-Befehl Input einzusetzen, um doch mehrere Zeichen empfangen zu
können.
Was ich aber nicht verstehe ist folgendes:
Declare sub serial0charmatch()
config serialin = buffered, size = 100, bytymatch = 13
dim incoming_data as string *100
do
print incoming_data
wait 2
loop
end
sub serial0charmatch()
input incoming_data noecho
'print incoming_data
end sub
das print in der hauptschleife gibt immer nur eine empfangene zeile aus.
Kommentiere ich das print in der serial0charmatch ein, dann gibt es alle
empfangenen zeilen aus - eben das, was ich benötige.
Warum ist es so?
Alex schrieb:
> das print in der hauptschleife gibt immer nur eine empfangene zeile aus.> Kommentiere ich das print in der serial0charmatch ein, dann gibt es alle> empfangenen zeilen aus - eben das, was ich benötige.>> Warum ist es so?
Wahrscheinlich deshalb, weil dieses print in der ISR mit dem Empfang
synchronisiert ist. Es gibt nur dann aus, wenn auch tatsächlich ein
String epfangen wurde. Wohingegen deine Hauptschleife auf biegen und
brechen ausgibt.
Auch interessant:
Die Ausgabe dauert ja auch seine Zeit.
Was passiert eigentlich, wenn während der Ausgabe die serial0charmatch
aufgerufen wird, und dem PRINT die Daten unter dem Allerwertesten
umdreht.
Nein daran scheint es nicht zu liegen:
Declare sub serial0charmatch()
config serialin = buffered, size = 100, bytymatch = 13
dim incoming_data as string *100
dim flag as byte
flag = 0
do
if flag = 1 then
print incoming_data
flag = 0
endif
wait 2
loop
end
sub serial0charmatch()
flag = 1
input incoming_data noecho
'print incoming_data
end sub
liefert das gleiche ergebnis - immer nur eine empfangene zeile
Bist du sicher, dass dein GPS Empfänger mit 9600 Baud sendet?
Meistens haben die nämlich nur 4800 Baud.
Die Schlussfolgerung wäre dann
$crystal = 16000000
Dein µC läuft in Wirklichkeit mit 8Mhz, so dass sich wieder korrekte
4800 ergben.
Aber:
wait 2
das werden dann 4 Sekunden Wartezeit
Karl Heinz:
Ich weiß es nicht genau ehrlich gesagt.
Ich habe es so gelöst, dass ich in der Interrupt-Routine den
Empfangsstring zerlegt habe und in zwei weiteren globalen Variablen die
MMC und GGA Strings gespeichert habe.
Sub Serial0charmatch()
Input Incoming_data Noecho
If Len(incoming_data) > 50 Then
Filter = Incoming_data
Subfilter = Mid(incoming_data , 2 , 6)
If Subfilter = "$GPRMC" And Mc = "" Then
Mc = Filter
End If
If Subfilter = "$GPGGA" And Ga = "" Then
Ga = Filter
End If
End If
Return
End Sub