mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Bascom UART Interrupt Problem


Autor: Filth __ (filth)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe ein Problem. Es sollen Daten von einem GPS Sensor gelesen 
werden. Speziell brauche ich nur die GPRMC und GPGGA Strings. Der Sensor 
sendet im NMEA format.

Allerdings wird irgendwie die Hälfte vom Empfang verschluckt, manchmal 
funktioniert es auch. Es scheint irgendein Timingproblem zu sein.

Hier ist der Code:
$regfile = "m644pdef.dat"
$crystal = 16000000
$hwstack = 128
$swstack = 512
$framesize = 128
$baud = 38400
$baud1 = 9600


' ************* GPS - TEIL ********************
Open "COM2:" For Binary As #2
Config Serialin = Buffered , Size = 100 , Bytematch = 10

Config Serialin1 = Buffered , Size = 100
Config Portb.6 = Input

Const Id_str_lg = 6                                         ' Länge des Identifiers
Dim Id_str As String * Id_str_lg                            ' ID String
Dim Buff_str_ovrl As String * 99 At _rs232inbuf0 Overlay    ' Einen String über den SerialIn Puffer legen

Dim Wr_ctr As Byte                                          ' Schreibzähler
Dim Wr_b As Byte
Dim Mc As String * 100                                      ' GPS MC - Teil
Dim Ga As String * 100                                      ' GPS GA - Teil
Dim Writestring As String * 30
Dim Length As Integer
Dim B_cpd As Byte                                           ' Hilfsvariable zum Kopieren der Bytes des Stringoverlays
Dim C_st As Byte
Mc = ""
Ga = ""
' ********************************************



Enable Interrupts



Do

Loop

End




'Daten vom Buffer auslesen
Serial0charmatch:

   Pushall

   B_cpd = _rs_bufcountr0 - 2                               ' Anzahl zu kopierender Zeichen des Pufferstrings
   C_st = _rs_head_ptr0 + 1                                 ' Startkopierposition im Pufferstring

   Id_str = Mid(buff_str_ovrl , C_st , Id_str_lg)           ' ID String holen, ab 2tem Zeichen, ohne $

   Print #2 , Buff_str_ovrl

   If Id_str <> "$GPGGA" And Id_str <> "$GPRMC" Then
      Clear Serialin
      Popall
      Return
   End If

   If Id_str = "$GPRMC" And Mc = "" Then
      Mc = Mid(buff_str_ovrl , C_st , B_cpd)                ' Puffer in den String kopieren, ohne $, ohne CR
   End If

   If Id_str = "$GPGGA" And Ga = "" Then
      Ga = Mid(buff_str_ovrl , C_st , B_cpd)                ' Puffer in den String kopieren, ohne $, ohne CR
   End If


   Clear Serialin

   Popall
Return


Die Ausgabe:
<\n>$GPGGA,205133.560,8960.0000,N,00000.0000,E,0,0,,137.0,M,13.0,M,,*46<\r>
<\n><\r>
<\n>$G33.560,V,8960.0000,N,00000.0000,E,0.00,0.00,190110,,,N*7C<\r>
<\n>M,,*46<\r>
<\n><\r>
<\n>$GPGGA,205133.760,8960.0000,N,00000.0000,E,0,0,,137.0,M,13.0,M,,*44<\r>
<\n><\r>
<\n>$G33.760,V,8960.0000,N,00000.0000,E,0.00,0.00,190110,,,N*7E<\r>
<\n>M,,*44<\r>
<\n><\r>
<\n>$GPGGA,205133.961,8960.0000,N,00000.0000,E,0,0,,137.0,M,13.0,M,,*4B<\r>
<\n><\r>
<\n>$G33.961,V,8960.0000,N,00000.0000,E,0.00,0.00,190110,,,N*71<\r>
<\n>M,,*4B<\r>
<\n><\r>
<\n>$GPGGA,205134.160,8960.0000,N,00000.0000,E,0,0,,137.0,M,13.0,M,,*45<\r>

Es wird immer nur der GPGGA-Teil aufgefangen. Hat evtl jemand eine Idee 
warum?

Danke

Autor: Filth __ (filth)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keiner eine Idee?

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Keiner eine Idee?

>Config Serialin = Buffered , Size = 100

Evtl. Puffer zu klein?

MfG Spess

Autor: Filth __ (filth)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

nein, daran dürfte es normallerweise nicht liegen, denn laut
http://tiny.cc/sMC3B
Auf Seite 7 sollte die Ausgabe bei etwa 68 Zeichen liegen. Das spricht 
auch dafür, dass es so ja auch schon funktioniert hat.

Kann es etwas mit dem voreilenden bzw nacheilenden Input-Problem zu tun 
haben?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich das richtig sehe, dann greifst du direkt auf den Buffer zu, den 
die RS232 benutzt um die Zeichen zu empfangen.

Jetzt sendet aber dein GPS weiter, während du noch den vorhergehenden 
String bearbeitest. D.h. während du einen String auswertest, wird der 
Anfang des Strings schon von den nächsten eintreffenden Zeichen 
überschrieben.

Nicht mit Overlay arbeiten, sondern den String umkopieren. Dann hast du 
Zeit den String zu bearbeiten, während im Hintergrund die nächsten 
Zeichen eintrudeln.

Denk auch drann, dass die Ausgabe des Strings auch Zeit braucht. Zeit in 
der wiederrum weitere Zeichen eintrudeln.

Autor: Filth __ (filth)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl Heinz,

stimmt das macht Sinn.
Aber ich kopiere den String ja eigentlich mit:
 Id_str = Mid(buff_str_ovrl , C_st , Id_str_lg)           ' ID String holen, ab 2tem Zeichen, ohne $

Oder reicht es so nicht? Wie würdest du es lösen?

Gruß
Alex

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex G. schrieb:
> Hallo Karl Heinz,
>
> stimmt das macht Sinn.
> Aber ich kopiere den String ja eigentlich mit:
>
>
>  Id_str = Mid(buff_str_ovrl , C_st , Id_str_lg)           ' ID String
> holen, ab 2tem Zeichen, ohne $
> 

Und wer sagt dir, dass in der Zeit die vergeht, bis BASCOM die Funktion 
aufruft und den PushAll gemacht hat, der Anfang von buff_str_ovrl nicht 
schon von den nächsten Zeichen überschrieben wurde?

Wie gehts denn weiter?

   Id_str = Mid(buff_str_ovrl , C_st , Id_str_lg)           ' ID String 
holen, ab 2tem Zeichen, ohne $

   Print #2 , Buff_str_ovrl

Du gibst danach den kompletten Buff_str_ovrl aus und anhand deines Logs 
ist ersichtlich

<\n>$GPGGA,205133.560,8960.0000,N,00000.0000,E,0,0,,137.0,M,13.0,M,,*46< 
\r>
<\n><\r>
<\n>$G33.560,V,8960.0000,N,00000.0000,E,0.00,0.00,190110,,,N*7C<\r>

dass da offenbar schon mit dem Buffer irgendwas passiert ist. Meines 
wissens beginnt kein NMEA Datensatz mit $G33.560

Etwas später machst du dann

   Clear Serialin

wodurch du alle Zeichen des nächsten Datensatzes, die in der 
Zwischenzeit eingetrudelt sind, verwirfst. Wenn also dein GPS in der 
ZWischenzeit gesendet hat (nur als Beispiel)

  $GPGGA,205133.560,8960.0000,N,00

dann verwirfst du das. Dein GPS Gerät kriegt das aber nicht mit und 
sendet munter weiter
   00.0000,E,0,0,,137.0,M,13.0,M,,*46

Bis irgendwann ein Zeilenende kommt und du anfängst diese Zeile 
auszuwerten. Die fängt jetzt aber nicht mit &GPGGA oder $GPRMC an, 
sondern mit 00.0000 weil du ja schlauerweise alles vorhergehende 
gelöscht hast :-)

> Oder reicht es so nicht? Wie würdest du es lösen?

Abchecken, ob das GPS Gerät Handshake unterstützt und es sofort nach dem 
Empfang einer Zeile zum Schweigen bringen.
Wenn das nicht geht, dann wirds wohl darauf hinauslaufen, die empfangene 
Zeile sofort in einem String in Sicherheit zu bringen und mit der Kopie 
zu arbeiten. Auf jeden Fall aber nicht dem BASCOM mit irgendwelchen 
clear Aktionen in die Buffer Verwaltung hineinpfuschen, BASCOM muss die 
volle Kontrolle über den Inhalt des Buffers haben, nur dann hast du eine 
Chance, dass die Zeilen auch vollständig sind.

Wenn sich das zeitlich nicht ausgeht, und das erste eintrudelnde Zeichen 
schon kommt, ehe die Zeile in Sicherheit gebracht werden kann, dann 
kannst du den BASCOM Mechanismus zum Empfang einer Zeile überhaupt nicht 
benutzten sondern musst dir selbst was machen, das mittels Double 
Buffering das Problem löst.

Autor: Klemm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deine ISR läuft an, sobald die erste Zeile empfangen wurde. Derweil Du 
den uC in der ISR beschäftigst, rauscht die 2. Zeile an Dir vorbei. 
Vermute ich mal.. :-)

Wozu brauchst Du interrupts und der ganzen config .. Schnickschnack? Du 
wirst ohnehin nicht jede Zeile interpretieren können. Einfacher so 
(Pseudocode, aber einfach umzusetzen:

do
  Emfangen:
  do
    do:loop until rxd
  loop until UDR = 10
  do
    if rxd then stringbuffer = stringbuffer + UDR
  loop until <Zeilenende "10" empfangen>
  do
    if rxd then stringbuffer = stringbuffer + UDR
  loop until <Zeilenende "10" empfangen>

  'jetzt haben wir mit Sicherheit 2 vollständige Zeilen

  Verarbeiten:
  'alles bis zum ersten Zeilenende wegwerfen
  'Stringbuffer enthält jetzt 2 saubere Zeilen

loop

Das Empfangen kann man natürlich noch schöner machen mit einer 
Schleife..

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sub Serial0bytereceived(s As String)
  S = ""
  Do
    B = Inkey()
    Select Case B
       Case 0
       Case 13
       Case 10 : If S <> "" Then Exit Do
       Case Else
         S = S + Chr(b)
    End Select
  Loop
End Sub

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.