Markus87
24.08.2011, 12:54
Hi, bin gerade dabei mich in Timer und Interrupts einzuarbeiten. Habe dafür ein kleines Programm geschrieben welches nach einem Tastendruck eine LED blinken lässt.
Der Tastendruck soll dabei die globalen interrupts freischalten und das LED blinken ist mit dem Timer 0 interrupt realisiert.
NOLIST
.INCLUDE "m16def.inc" ; Headerdatei fuer Atmega 16
.LIST
;
;
; ============================================
; R E G I S T E R D E F I N I T I O N E N
; ============================================
.DEF rmp = R16 ; Vielzweckregister
;
;
; ==============================================
; R E S E T V E K T O R
; ==============================================
;
.CSEG
.ORG $0000
rjmp Main ; Reset-Vektor
; ==============================================
; INTERRUPTS
; ==============================================
.ORG OVF0addr ; Timer 0 overflow
rjmp schalten
;
; ============================================
; H A U P T P R O G R A M M I N I T
; ============================================
;
Main:
;
ldi rmp,0x02 // PORT A1 Ausgang, rest Eingang
out DDRA,rmp
ldi rmp,0x00
out PORTA,rmp // PORT A initialisieren
sbi PORTA,0 // Pull-up für PORT A0 aktivieren
//// Timer 0 konfigurieren
ldi rmp,0x05 // Prescaler 1024
out TCCR0,rmp
ldi rmp,0x01 // Interrupt bei Timer Overflow
out TIMSK,rmp
cli // Globale Interrupts deaktivieren
;
; ============================================
; P R O G R A M M - S C H L E I F E
; ============================================
;
Loop:
wdr
sbis PINA,0 // nächsten Befehl überspringen, wenn Taster nicht gedrückt ist
sei // Timer starten
rjmp loop // Zurueck nach Loop
/// -----------------------------------
/// Zum ein und ausschalten der LED
schalten:
in rmp,PINA // Zustand von LED einlesen
ldi R17, 0xFF //
eor R17,rmp // exor um LED Zustand zu wechseln
sbrc R17,1 // LED einschalten überspringen, wenn beim exor 0 rauskommt.
sbi PORTA,1 // LED einschalten
sbrs R17,1 // LED ausschalten überspringen, wenn beim exor 1 rauskommt.
cbi PORTA,1 // LED ausschalten
/// -----------------------------------
Wenn ich oben im deklarationsteil das deaktivieren der Interrupts per cli weglasse dann funktioniert alles so wie gedacht. Wenn ich jedoch cli dort stehen lasse blinkt die LED nur solange ich den Taster gedrückt lasse. Es scheint also so als ob nach ablauf der ISR Routine "Schalten" der Controller wieder beim Initialisierungsteil anfängt und dann wieder auf cli stößt. Aber normal müsste er doch nach ablauf der ISR wieder in der Loop Schleife landen, wie kommt er dann zu dem cli im Initialisierungsteil ?
Der Tastendruck soll dabei die globalen interrupts freischalten und das LED blinken ist mit dem Timer 0 interrupt realisiert.
NOLIST
.INCLUDE "m16def.inc" ; Headerdatei fuer Atmega 16
.LIST
;
;
; ============================================
; R E G I S T E R D E F I N I T I O N E N
; ============================================
.DEF rmp = R16 ; Vielzweckregister
;
;
; ==============================================
; R E S E T V E K T O R
; ==============================================
;
.CSEG
.ORG $0000
rjmp Main ; Reset-Vektor
; ==============================================
; INTERRUPTS
; ==============================================
.ORG OVF0addr ; Timer 0 overflow
rjmp schalten
;
; ============================================
; H A U P T P R O G R A M M I N I T
; ============================================
;
Main:
;
ldi rmp,0x02 // PORT A1 Ausgang, rest Eingang
out DDRA,rmp
ldi rmp,0x00
out PORTA,rmp // PORT A initialisieren
sbi PORTA,0 // Pull-up für PORT A0 aktivieren
//// Timer 0 konfigurieren
ldi rmp,0x05 // Prescaler 1024
out TCCR0,rmp
ldi rmp,0x01 // Interrupt bei Timer Overflow
out TIMSK,rmp
cli // Globale Interrupts deaktivieren
;
; ============================================
; P R O G R A M M - S C H L E I F E
; ============================================
;
Loop:
wdr
sbis PINA,0 // nächsten Befehl überspringen, wenn Taster nicht gedrückt ist
sei // Timer starten
rjmp loop // Zurueck nach Loop
/// -----------------------------------
/// Zum ein und ausschalten der LED
schalten:
in rmp,PINA // Zustand von LED einlesen
ldi R17, 0xFF //
eor R17,rmp // exor um LED Zustand zu wechseln
sbrc R17,1 // LED einschalten überspringen, wenn beim exor 0 rauskommt.
sbi PORTA,1 // LED einschalten
sbrs R17,1 // LED ausschalten überspringen, wenn beim exor 1 rauskommt.
cbi PORTA,1 // LED ausschalten
/// -----------------------------------
Wenn ich oben im deklarationsteil das deaktivieren der Interrupts per cli weglasse dann funktioniert alles so wie gedacht. Wenn ich jedoch cli dort stehen lasse blinkt die LED nur solange ich den Taster gedrückt lasse. Es scheint also so als ob nach ablauf der ISR Routine "Schalten" der Controller wieder beim Initialisierungsteil anfängt und dann wieder auf cli stößt. Aber normal müsste er doch nach ablauf der ISR wieder in der Loop Schleife landen, wie kommt er dann zu dem cli im Initialisierungsteil ?