www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Bascom und UART wiedermal


Autor: Toni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Tag zusammen!

Ich habe ein Problem mit dem UART von meinem ATmega32 und ankommenden 
Befehlen. Das Protokoll besteht aus 4 Bytes, die ausgewertet werden.
Wenn nun andere Sachen am UART ankommen, die mehr als 4 Bytes haben dann 
hängt sich das Programm auf. Woran könnte das liegen? Hier der Code:
On Urxc Receive
Enable Urxc

Enable Interrupts

Dim I as Byte
Dim Frame(4) as Byte
Dim Byte1 as Byte
Dim Byte2 as Byte
Dim Byte3 as Byte
Dim Byte4 as Byte

Main:
Do
  If I = 4 and Byte1 = &H10 and Byte2 = &H20 and Byte4 = &H40 Then
    Select Case Byte3
      Case &H01 :

      Case &H02 :
    End Select
    I = 0
  End If
Loop

Receive:
  Incr I
  Frame(i) = UDR
  Byte1 = Frame(1)
  Byte2 = Frame(2)
  Byte3 = Frame(3)
  Byte4 = Frame(4)
Return


Danke schonmal und schönen Tag,
Toni

Autor: Bascoms Liebling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frame(i) = ..

geh schief wenn i größer als 4 wird... das mußt du abfangen in deinem 
receive

Autor: Thomas H. (pcexperte) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weil I 5 wird wenn nicht deine gewünschte Bytefolge in der IF Abfrage 
ankommt und dein Array nur 4 Byte groß ist.

Mach mal das hier:
On Urxc Receive
Enable Urxc

Enable Interrupts

Dim I as Byte
Dim Frame(4) as Byte
Dim Byte1 as Byte
Dim Byte2 as Byte
Dim Byte3 as Byte
Dim Byte4 as Byte

Main:
Do
  If I = 4 then
    If Byte1 = &H10 and Byte2 = &H20 and Byte4 = &H40 Then
      Select Case Byte3
        Case &H01 :

        Case &H02 :
      End Select
    End If
    I = 0
  End If
Loop

Receive:
  Incr I
  Frame(i) = UDR
  Byte1 = Frame(1)
  Byte2 = Frame(2)
  Byte3 = Frame(3)
  Byte4 = Frame(4)
Return

Autor: Toni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Letzteres Beispiel habe ich versucht. Gleiches Problem wie vorher.
Muss ich vielleicht schon in der Interrupt Routine die überschüssigen 
Bytes löschen/ignorieren?

Wenn ja wie mach ich das?

Toni

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
omg... vorab ich kann kein BASCOM..

Programmier erstmal ein LED blinken und so...

Receive:
  Incr I
  If I < 4 then
     Frame...
     ...
  End If
Return

vlt. noch ein Dummy readout von udr im else zweig aber sonst

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

Bewertung
0 lesenswert
nicht lesenswert
Diese ganze Auswertung ist ziemlicher Müll, weil der Empfänger nie 
wieder synchronisiert, wenn er einmal ausser Tritt gekommen ist (zb. 
weil der Sender mal 5 Bytes statt 4 gesendet hat)

Frag dich einfach mal (bzw. spiels in Gedanken durch) was passiert wenn 
der Sender

  &H00 &H80 &H10 &H20 &H01 &H40 &H10 &H20

sendet (zb. weil dein Mega mitten in eine laufende Übertragung 
einsteigt). Wie kann er aus dem Datenstrom den gültigen Frame  &H10 &H20 
&H01 &H40 rausfiltern und darauf reagieren?
Die Antwort darauf ist nicht: indem er darauf wartet, dass jeweils 4 
Bytes zusammen gekommen sind. Denn dann würde deine Erkennung die ersten 
4 Bytes

 &H00 &H80 &H10 &H20

untersuchen, feststellen dass das kein gültiger Frame war und auf die 
nächsten 4 Bytes warten

 &H01 &H40 &H10 &H20

ebenfalls kein gültiger Frame. Und so gehts dann weiter (Genau das was 
ich oben sagte: Dein Empfänger synchronisiert sich nicht mehr, wenn er 
einmal ausser Tritt gekommen ist)

Funktionieren tut das nur, indem man nach jedem empfangenen Byte die 4 
zuletzt Empfangenen untersucht (wenn denn schon 4 Empfangen wurden) und 
nachsieht ob das ein gültiger Frame war.

Das erste Byte kommt rein: &H00

  &H00            (noch keine 4 vorrätig, daher keine Analyse möglich)

Das nächste kommt rein: &H80

  &H00 &H80            (erst 2, 4 sind aber notwendig)

Das nächste: &H10

  &H00 &H80 &H10       (erst 3, immer noch keine 4)

Nächster Empfang: &H20

  &H00 &H80 &H10 &H20   jetzt sinds 4, aber das ist kein gültiger Frame
                        -> keine Aktion

Nächster Empfang: &H01
Das erste zwischengespeicherte Byte wird verworfen, alle anderen rücken 
nach

  &H80 &H10 &H20 &H01   immer noch kein gültiger Frame

Nächster Empfang: &H40

  &H10 &H20 &H01 &H40   holla, diese 4 Bytes sind ein gültiger Frame
                        -> Auswerten und den Empfangsbuffer löschen

Nächster Empfang: &H10

  &H10                  noch keine 4 Bytes empfangen

Nächster Empfang: &H20

  &H10 &H20

....


Und wozu das Frame-Array gut sein soll, ist mir auch nicht wirklich 
klar.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Und wozu das Frame-Array gut sein soll, ist mir auch nicht wirklich
> klar.
Mir auch nicht...
Es reicht die Erkennung der Startsequenz:
Main:
Do
  If datensindda=1 then
    Select Case datenbyte
      Case &H01 :

      Case &H02 :
    End Select
    datensindda=0   <-- Daten verarbeitet
  End If
Loop


Receive:
  rcvbyteold = rcvbyte
  rcvbyte = UDR
  if getbyte=1 then
     datenbyte=rcvbyte     
     datensindda=1   <-- Handshake
     getbyte=0;
  end if
  if rcvbyte=&H10 and rcvbyteold=&H20 then   <-- auf Startsequenz synchronisieren
     getbyte=1   <-- nächstes Byte einlesen
  end if
Return

Autor: Toni (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo und vielen Dank für die Antworten. Habe das jetzt verstanden. Das 
Programm von Lothar Miller funktioniert soweit einwandfrei, nur die 
Zeile:

if rcvbyte=&H10 and rcvbyteold=&H20 then

muss in

if rcvbyte=&H20 and rcvbyteold=&H10 then

geändert werden (weil zuerst &H10 ankommt und dann &H20)

Jetzt habe ich das ganze erweitert und will aus einem Paket 4 Bytes 
rausholen, die nach &H60 &H40 kommen. Ich habe das jetzt so eingebunden 
und es funktioniert. Ist das der richtige Weg oder gibt es vielleicht 
eine elegantere Lösung:
Dim daten(4) as Byte
Dim rcvbyte as Byte
Dim rcvbyteold as Byte
Dim datensindda as Bit
Dim Getbyte as Bit
Dim i as Byte

rcvbyteold = rcvbyte
rcvbyte = UDR

If Getbyte = 1 Then
  daten(i) = rcvbyte
  incr i
  If i = 4 Then
    i = 1
    datensindda = 1
    Getbyte = 0
  End If
End If

If rcvbyte = &H40 and rcvbyteold = &H60 Then
  Getbyte = 1
End If

Toni

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.