hi! habe ein problem mit dem interrupt. bei mir soll er bei einer änderung an dem uart eingangspins des atmega 8 eine inerrupt rutine durchlaufen. welchen inerrupt nimmt man denn dazu???? irgendwie geht das bei mir nämlich nicht. habe den 12 0x00B USART, RX USART-Empfang abgeschlossen genommen. aber damit funzt es irgendwie nicht. bei einem reset macht er das was er soll aber dann nicht mehr!!! kann mir da bitte einer helfen?
kann man nehmen, allerdings musst du in der Rx-ISR vor reti das UDR-Register lesen, damit das entsprechende flag zurückgesetzt wird. Sonst wird direkt ein neuer int ausgelöst, obwohl nichts passiert ist. Aber, wie immer, ein paar Zelen Code sagen mehr als eine umständliche, unvollständige Beschreibung.
na gut, wenn du meinst! werd ich den code mal posten. aber der ist etwas wirr. da ich nun mal ein anfänger bin. .include "m8def.inc" .def temp = r16 .equ CLOCK = 4000000 .equ BAUD = 37000 .equ UBRRVAL = CLOCK/(BAUD*16)-1 .org 0x000 rjmp main0 reti reti reti reti reti reti reti reti reti reti rjmp int_rxc reti reti reti reti reti reti reti main0: ; Stackpointer initialisieren ldi temp, LOW(RAMEND) out SPL, temp ldi temp, HIGH(RAMEND) out SPH, temp ; Baudrate einstellen ldi temp, LOW(UBRRVAL) out UBRRL, temp ldi temp, HIGH(UBRRVAL) out UBRRH, temp ; Frame-Format: 8 Bit ldi temp, (1<<URSEL)|(3<<UCSZ0) out UCSRC, temp weiter: sbi UCSRB,TXEN ; TX aktivieren sbi UCSRB, RXCIE sbi UCSRB, RXEN sei loop: rjmp weiter main1: rcall zeit rcall zeit rcall zeit rcall zeit rcall zeit rcall zeit ldi temp, 8 rcall serout ; Unterprogramm aufrufen rcall zeit ldi temp, 0 rcall serout rcall zeit ; Unterprogramm aufrufen . . . . rjmp loop serout: sbis UCSRA,UDRE ; Warten bis UDR für das rjmp serout out UDR, temp ret ; zurück zum Hauptprogramm ; ============================= ; Warteschleifen-Generator ; 800 Zyklen: ; ----------------------------- ; warte 798 Zyklen: zeit: ldi R17, $03 WGLOOP0: ldi R18, $84 WGLOOP1: dec R18 brne WGLOOP1 dec R17 brne WGLOOP0 ret int_rxc: push temp rjmp main1 in temp, UDR pop temp reti
jetzt habe ich das programm gepostet aber keiner schreibt meht etwas. ist es denn so schlecht???
au weia! loop: rjmp weiter //Schwachsinn, aber nicht tragisch der Hund lauert hier: int_rxc: push temp rjmp main1 // ganz schlecht, eine ISR mit jmp verlassen // da dadurch reti nicht erreicht wird // und damit die ints nicht wieder freigegeben werden //nebenbei bekonmmst du damit ein stackproblem in temp, UDR pop temp reti
das verstehe ich nicht ganz! der Hund lauert hier: int_rxc: push temp rjmp main1 // ganz schlecht, eine ISR mit jmp verlassen // da dadurch reti nicht erreicht wird // und damit die ints nicht wieder freigegeben werden komme doch nach dem jump befehl wieder zurück in die interruptroutine und dann kommt der reti.... oder ist das nicht so? was meinst du mit stackproblem??? //nebenbei bekonmmst du damit ein stackproblem in temp, UDR pop temp reti
wo steht, dass du zurückkommst? Zurück kämst du, wenn du irgendwas anderes mit call aufrufst, und dort dann irgendwann ein return steht, bei jmp ist die Rückkehradresse futsch. Machs doch nicht komplizierter, als es ist. Setz dir in der ISR ein flag, welches anzeigt, dass ein Zeichen empfangen wurde, kann ein einzelnes Bit sein oder du benutzt ein komplettes Register. Hier mal ein Beispiel mit Register, hat einen kleinen Schönheitsfehler, dass es auf empfangenes Zeichen 0 nicht reagiert, aber das Prinzip wird klar clr rec_byte main_loop: tst rec_byte breq main_loop //warte bis rec_byte >0 dein_kram rjmp main_loop int_rxc: push r2 in r2, sreg //sollte man (fast) immer sichern in rec_byte, UDR out sreg, r2 pop r2 reti
also das was du da geschrieben hast habe ich noch nicht ganz verstanden. weis noch icht ganz was das macht. habe jetzt mein programm so geändert: .include "m8def.inc" .def temp = r16 .equ CLOCK = 4000000 .equ BAUD = 37000 .equ UBRRVAL = CLOCK/(BAUD*16)-1 .org 0x000 rjmp main0 reti reti reti reti reti reti reti reti reti reti rjmp int_rxc reti reti reti reti reti reti reti main0: ; Stackpointer initialisieren ldi temp, LOW(RAMEND) out SPL, temp ldi temp, HIGH(RAMEND) out SPH, temp ; Baudrate einstellen ldi temp, LOW(UBRRVAL) out UBRRL, temp ldi temp, HIGH(UBRRVAL) out UBRRH, temp ; Frame-Format: 8 Bit ldi temp, (1<<URSEL)|(3<<UCSZ0) out UCSRC, temp weiter: sbi UCSRB,TXEN ; TX aktivieren sbi UCSRB, RXCIE sbi UCSRB, RXEN sei loop: rjmp loop serout: sbis UCSRA,UDRE ; Warten bis UDR für das nächste rjmp serout out UDR, temp ret ; zurück zum Hauptprogramm ; ============================= ; Warteschleifen-Generator ; 800 Zyklen: ; ----------------------------- ; warte 798 Zyklen: zeit: ldi R17, $03 WGLOOP0: ldi R18, $84 WGLOOP1: dec R18 brne WGLOOP1 dec R17 brne WGLOOP0 ret int_rxc: push temp rcall zeit rcall zeit rcall zeit rcall zeit rcall zeit rcall zeit ldi temp, 8 rcall serout ; Unterprogramm aufrufen rcall zeit ldi temp, 0 rcall serout rcall zeit ; Unterprogramm aufrufen ldi temp, 0 rcall serout rcall zeit ; ... ldi temp, 0 rcall serout rcall zeit ldi temp, 0 rcall serout rcall zeit ldi temp, 17 rcall serout rcall zeit ldi temp, 0 rcall serout rcall zeit ldi temp, 0 rcall serout rcall zeit ldi temp, 40 rcall serout rcall zeit ldi temp, 0 rcall serout rcall zeit ldi temp, 70 rcall serout rcall zeit ldi temp, 118 rcall serout rcall zeit ldi temp, 60 rcall serout rcall zeit ldi temp, 0 rcall serout rcall zeit ldi temp, 0 rcall serout rcall zeit ldi temp, 0 rcall serout rcall zeit ldi temp, 25 rcall serout rcall zeit ldi temp, 1 rcall serout rcall zeit ldi temp, 0 rcall serout rcall zeit ldi temp, 0 rcall serout rcall zeit in temp, UDR out portd, temp pop temp reti irgedwie funktioniert das auch, nur schickt er mir die ausgabe die ich mache zweimal. der läuft die interruptrotine zweimal durch. aber wieso???? ich versteh das irgendwie nicht??? hast du dazu eine idee?
Ein bißchen viel Code - aber wo wird eigentlich das Statusregister in der INT-Routine gerettet ?
jetzt raff ich gar nichts mehr mit den doofen interrupts.... wie ist das jetzt? mit sei aktiviere ich alle mit cli kann ich sie deaktivieren. wenn ich einen interrupt hatte, muss ich aber kein flag zurücksetzen oder? macht er automatisch!? was ist wenn ich noch einen interrupt bekomme wenn gerade einer ausgeführt wird? merkt er sich den und macht es dann später? habe versucht mit cli die interrupts dann während des ausführen eine interrupts zu unterdrücken. bewirkt aber nichts... schrott... bei mir führt er die interruptroutine so wie es aussieht immer zweimal hintereinander aus. ich raffs nich mehr...*flenn*
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.