Forum: Mikrocontroller und Digitale Elektronik UART - Serialin Bascom


von Alex (Gast)


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!

von Karl H. (kbuchegg)


Lesenswert?

Config Serialin1 = Buffered , Size = 20 , Bytematch = 13

und du denkst wirklich, dass deine kompletten Zeilen in 20 Zeichen Platz 
haben?

von Alex (Gast)


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.

von Karl H. (kbuchegg)


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.

von Gast_ (Gast)


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

von D. S. (jasmin)


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

von usb (Gast)


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

von D. S. (jasmin)


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.

von Alex (Gast)


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?

von Karl H. (kbuchegg)


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.

von Alex (Gast)


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

von Karl H. (kbuchegg)


Lesenswert?

Wartest du auch lange genug?
2 Sekunden können sich ziehen, wenn man darauf wartet.
(wozu warten, wenn du jetzt sowieso eine Flagsteuerung hast?)

von Karl H. (kbuchegg)


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

von Alex (Gast)


Lesenswert?

Bzgl der 9600 bin ich mir sicher - sonst wären ja die empfangenen Daten 
nur noch Müll. Der Sensor ist mit 9600 im Datenblatt angegeben.

Mfg
Alex

von Simon K. (simon) Benutzerseite


Lesenswert?

Oder dein Mikrocontroller läuft in Wirklichkeit mit 8MHz. Du musst auch 
mal lesen, was man schreibt.

von Alex (Gast)


Lesenswert?

Habs selbst gelöst. danke

von D. S. (jasmin)


Lesenswert?

Ja, nee is klar !

Und denen welche geholfen haben ist das jetzt das Feedback ???

von Alex (Gast)


Lesenswert?

90% dumme Sprüche im Thread, da hat man wenig Bock auf Feedback. Hau 
rein

von Karl H. (kbuchegg)


Lesenswert?

Und was wars jetzt?

von Alex (Gast)


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

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
Noch kein Account? Hier anmelden.