Forum: Mikrocontroller und Digitale Elektronik Bascom und UART wiedermal


von Toni (Gast)


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:
1
On Urxc Receive
2
Enable Urxc
3
4
Enable Interrupts
5
6
Dim I as Byte
7
Dim Frame(4) as Byte
8
Dim Byte1 as Byte
9
Dim Byte2 as Byte
10
Dim Byte3 as Byte
11
Dim Byte4 as Byte
12
13
Main:
14
Do
15
  If I = 4 and Byte1 = &H10 and Byte2 = &H20 and Byte4 = &H40 Then
16
    Select Case Byte3
17
      Case &H01 :
18
19
      Case &H02 :
20
    End Select
21
    I = 0
22
  End If
23
Loop
24
25
Receive:
26
  Incr I
27
  Frame(i) = UDR
28
  Byte1 = Frame(1)
29
  Byte2 = Frame(2)
30
  Byte3 = Frame(3)
31
  Byte4 = Frame(4)
32
Return

Danke schonmal und schönen Tag,
Toni

von Bascoms Liebling (Gast)


Lesenswert?


von ... .. (docean) Benutzerseite


Lesenswert?

Frame(i) = ..

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

von Thomas H. (pcexperte) Benutzerseite


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:
1
On Urxc Receive
2
Enable Urxc
3
4
Enable Interrupts
5
6
Dim I as Byte
7
Dim Frame(4) as Byte
8
Dim Byte1 as Byte
9
Dim Byte2 as Byte
10
Dim Byte3 as Byte
11
Dim Byte4 as Byte
12
13
Main:
14
Do
15
  If I = 4 then
16
    If Byte1 = &H10 and Byte2 = &H20 and Byte4 = &H40 Then
17
      Select Case Byte3
18
        Case &H01 :
19
20
        Case &H02 :
21
      End Select
22
    End If
23
    I = 0
24
  End If
25
Loop
26
27
Receive:
28
  Incr I
29
  Frame(i) = UDR
30
  Byte1 = Frame(1)
31
  Byte2 = Frame(2)
32
  Byte3 = Frame(3)
33
  Byte4 = Frame(4)
34
Return

von Toni (Gast)


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

von ... .. (docean) Benutzerseite


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

von Karl H. (kbuchegg)


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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Und wozu das Frame-Array gut sein soll, ist mir auch nicht wirklich
> klar.
Mir auch nicht...
Es reicht die Erkennung der Startsequenz:
1
Main:
2
Do
3
  If datensindda=1 then
4
    Select Case datenbyte
5
      Case &H01 :
6
7
      Case &H02 :
8
    End Select
9
    datensindda=0   <-- Daten verarbeitet
10
  End If
11
Loop
12
13
14
Receive:
15
  rcvbyteold = rcvbyte
16
  rcvbyte = UDR
17
  if getbyte=1 then
18
     datenbyte=rcvbyte     
19
     datensindda=1   <-- Handshake
20
     getbyte=0;
21
  end if
22
  if rcvbyte=&H10 and rcvbyteold=&H20 then   <-- auf Startsequenz synchronisieren
23
     getbyte=1   <-- nächstes Byte einlesen
24
  end if
25
Return

von Toni (Gast)


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:
1
Dim daten(4) as Byte
2
Dim rcvbyte as Byte
3
Dim rcvbyteold as Byte
4
Dim datensindda as Bit
5
Dim Getbyte as Bit
6
Dim i as Byte
7
8
rcvbyteold = rcvbyte
9
rcvbyte = UDR
10
11
If Getbyte = 1 Then
12
  daten(i) = rcvbyte
13
  incr i
14
  If i = 4 Then
15
    i = 1
16
    datensindda = 1
17
    Getbyte = 0
18
  End If
19
End If
20
21
If rcvbyte = &H40 and rcvbyteold = &H60 Then
22
  Getbyte = 1
23
End If

Toni

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.