Forum: Mikrocontroller und Digitale Elektronik UART string empfang


von Manuel (Gast)


Lesenswert?

Hi!

Ich habe jetz ne ganze Zeit das Forum durchsucht, jedoch leider keine 
konkrete lösung gefunden.

Ich will mit meinem Mega16 einen Datenstring von 6 Byte empfangen und in 
6 registern ablegen. Es sind immer genau 6 Byte, die dann der reihe nach 
in festgelegte register geschoben werden.

Den empfang regel ich über den RXC interrupt.
Wenn nun der interrupt ausgelöst wird, also das erste byte übertragen 
ist so wird doch, nachdem das nächste byte da ist, wieder ein int 
ausgelöst oder?
Das sollte aber den avr nicht stören da er erstmal den ersten interrupt 
zuende bringt, sehe ich das richtig?

Wenn ja, kann ich doch in der RXC routine eine schleife machen, die nach 
dem ersten byte noch 5 mal das rxc bit abfragt, und dann das byte ins 
zugehörige register schiebt. Aber danach muss ich das RXC bit manuell 
löschen oder?

Ich habe mir das ungefähr so vorgestellt:

int_RXD:

  in reg1, UDR

1:  sbis UCSRA, RXC  ; abfrage wiederholen bis RXC bit gesetzt ist
  jmp 1
  in reg2, UDR
  clb UCSRA, RXC

2:  sbis UCSRA, RXC
    jmp 2
  in reg3, UDR
  clb UCSRA, RXC

3:  sbis UCSRA, RXC
    jmp 3
  in reg4, UDR
  clb UCSRA, RXC

4:  sbis UCSRA, RXC
    jmp 4
  in reg5, UDR
  clb UCSRA, RXC

5:  sbis UCSRA, RXC
    jmp 5
  in reg6, UDR
  clb UCSRA, RXC      ; RXC bit löschen, um nicht gleich
                             ; wieder einen Interrupt auszulösen

reti


Das Problem ist, das diese 6 byte sehr oft hintereinander gesendet 
werden können. Würde das so funktionieren?

MfG
Manuel

von Walter (Gast)


Lesenswert?

in Assembler bin ich zwar nicht firm, d.h. ich weiß nicht genau was du 
da machst,
aber auf jeden Fall solltest im Interrupt keine Zeit verdödeln damit 
kein weiterer dazwischen funkt,
also Byte holen und wieder raus!

von Sonic (Gast)


Lesenswert?

Ich weiß nicht ob du die Gegenseite umprogrammieren kannst, aber 'ne 
Start- und Ende-Kennung wäre für eine Übertragung nicht schlecht. Dann 
brauchst du nur nach der Startmarke die Bytes zählen und einer 
SRAM-Adresse zuweisen. Nach dem 6. Byte oder der Schlusskennung setzt du 
den Bytezähler wieder auf '0'. In Assembler macht man sowas 
normalerweise mit Zeigern (X, Y oder Z), siehe Datenblatt. Das heißt, 
nach erkannter Starmarke Zeiger auf Anfang deines Arrays, byte für byte 
den Zeiger hochzählen und das Empfangene Byte in der SRAM-Adresse 
ablegen, auf die der Zeiger zeigt.

von Manuel (Gast)


Lesenswert?

@ Walter:
Das mit dem Interrupt sollte wohl kein Problem darstellen, da der UART 
interrupt der einzige ist, der an diesem controller ausgelöst werden 
kann.

@ Sonic:

Ja, ich kann die gegenseite umprogrammieren, aber ne enderkennung 
brauche ich doch eigentlich nicht, da ich davon ausgehen kann, das nach 
dem sechsten Byte der string komplett ist.

Es ist doch eigentlich das gleiche wie mit Zeigern zu arbeiten, wenn ich 
die daten direkt in ein register stecke nur das es eben nicht im SRAM 
steht.

von unscheinbarer WM-Rahul (Gast)


Lesenswert?

>Ja, ich kann die gegenseite umprogrammieren, aber ne enderkennung
>brauche ich doch eigentlich nicht, da ich davon ausgehen kann, das nach
>dem sechsten Byte der string komplett ist.

Wichtiger als eine Ende-Erkennung ist eine Starterkennung.
Wenn der Empfänger nämlich mal aus irgendwelchen Gründen den Start 
verpasst hat (z.B. es trat mittendrin ein Reset auf), dann sollte er 
sich auf den Sender bzgl. der Bytereihenfolge synchronisieren können.
Also entweder ein Startbyte (oder mehrere) vereinbaren oder nach dem 
letzten Byte eine so lange Pause machen, dass der Empfänger daran das 
Ende einer Übertragung erkennt und so sein Feld wieder von vorne 
befüllen kann.

von unscheinbarer WM-Rahul (Gast)


Lesenswert?

Ich würde übrigens eine Schleife zum Abfragen benutzen, dann muß man 
nicht alles sechsfach tippen (oder fünfmal kopieren...).

von Sonic (Gast)


Lesenswert?

Darum die Zeiger, ob die nun auf's SRAM oder Register zeigen ist 
unerheblich. Aber die oben genannte Schleife brauchst du nicht, nur im 
RX-INT den Zeiger hochzählen bis das sechste Byte erreicht ist und per 
Zeiger-Adressierung das empfangene Byte zuweisen.

von Walter (Gast)


Lesenswert?

wenn du im RX Interrupt wartest, wird durchaus ein weiterer Interrupt 
auftreten,
nämlich wenn das nächste Byte kommt kommt der RX Interrupt noch mal ...

von Manuel (Gast)


Lesenswert?

int_RXD:

  in temp, UDR
  inc zeiger

  cpi zeiger, 1
  breq 1
  cpi zeiger, 2
  breq 2
  cpi zeiger, 3
  breq 3
  cpi zeiger, 4
  breq 4
  cpi zeiger, 5
  breq 5
  cpi zeiger, 6
  breq 6
  rjmp ret  ; fehler


1:    mov reg1, temp
  rjmp ret
2:  mov reg2, temp
  rjmp ret
3:  mov reg3, temp
  rjmp ret
4:  mov reg4, temp
  rjmp ret
5:  mov reg5, temp
  rjmp ret
6:  mov reg6, temp
  rjmp ret

ret:  ldi zeiger, 0
  reti

Habe ich das so einigermaßen richtig verstanden?

von Manuel (Gast)


Lesenswert?

Oben war ein fehler drin, so müsste es laufen.
Ich kann mir jetzt nur nicht vorstellen wie das mit nem start und 
stopbit funktionieren soll, denn das problem ist, das ich keine ASCII 
zeigen, sonder zahlen sende die ein anderer controller hochzählt. das 
heißt, es kann jeder von den 256 werten vorkommen. Wenn ich also den UDR 
bzw. temp nach einem start oder stopbit kontrolliere, könnte das genauso 
zb. das drite byte sein...

int_RXD:

  in temp, UDR
  inc temp2

  cpi zeiger, 1
  breq 1
  cpi zeiger, 2
  breq 2
  cpi zeiger, 3
  breq 3
  cpi zeiger, 4
  breq 4
  cpi zeiger, 5
  breq 5
  cpi zeiger, 6
  breq 6

1:    mov reg1, temp
  rjmp ret
2:  mov reg2, temp
  rjmp ret
3:  mov reg3, temp
  rjmp ret
4:  mov reg4, temp
  rjmp ret
5:  mov reg5, temp
  rjmp ret
6:  mov reg6, temp
  ldi zeiger, 0
         rjmp ret

ret:  reti

von rene (Gast)


Lesenswert?

inc(zeiger) fehlt noch. push & pop der benutzten register plus des 
statusregisters, und dann koennte man sich den "case(zeiger)of" mit ner 
addition ersparen.

rene

von Walter (Gast)


Lesenswert?

den Zeiger auf 1 setzen anstatt auf 0

Walter

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.