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.