www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik UART string empfang


Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: unscheinbarer WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: unscheinbarer WM-Rahul (Gast)
Datum:

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

Autor: Sonic (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ...

Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: rene (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
den Zeiger auf 1 setzen anstatt auf 0

Walter

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.