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
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!
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.
@ 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.
>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.
Ich würde übrigens eine Schleife zum Abfragen benutzen, dann muß man nicht alles sechsfach tippen (oder fünfmal kopieren...).
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.
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 ...
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?
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.