UART - Serialin Bascom

Gast #1532766
Lesenswert?

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!
Gast #1532791
Lesenswert?

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.
#1532792
Lesenswert?

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.
Gast #1532796
Lesenswert?

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
#1532797
Lesenswert?

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
Gast #1532838
Lesenswert?

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
#1532898
Lesenswert?

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.
Gast #1532930
Lesenswert?

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?
#1532942
Lesenswert?

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.
Gast #1532943
Lesenswert?

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
#1532950
Lesenswert?

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
Gast #1533181
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren