Hallo mare_crisium,
habe den Code zum Tasten_3 nach Deinen Vorschlaegen angepasst.
Teil 1war ja im Prinzip nur das Sichern der Register in den Unterprogrammen.
Das Register 17 kann ich nicht mit Sichern, da ich es als Zaehlvariable in der ISR benutze.
Mit R16 – temp kein Problem. Funktioniert:
Code:
;***** STK500 Lernprogramm Nr.3c
;*** Aufgabe: alle LEDs mit einem Taster auf dem STK500 schalten
;*** 1. Tastendruck: LEDs einschalten
;*** 2. Tastendruck: LEDs blinken
;*** 3. Tastendruck: LEDs ausschalten
;*** zum Entprellen soll ein Interrupt(Int0) benutzt werden
;***
.include "m8515def.inc"
.def Temp = r16 ; Temporary register
.def Tast_Stat = r17 ; Zaehler fuer Taste in ISR
.def Delay = R18 ; Wartezeit
.def Delay2 = R19 ; Wartezeit
;*****
;Reset and Interrupt vector ;VNr. Beschreibung
rjmp RESET ;1 POWER ON RESET
rjmp INT0_ISR ;2 Int0-Interrupt
reti ;3 Int1-Interrupt
reti ;4 TC1 Capture
reti ;5 TC1 Compare Match A TC2 Overflow
reti ;6 TC1 Compare Match B TC1 Capture
reti ;7 TC1 Overflow TC1 Compare Match A
reti ;8 TC0 Overflow TC1 Compare Match B
reti ;9 SPI, STC Serial Transfer Complete TC1 Overflow
reti ;10 UART Rx Complete TC0 Overflow
reti ;11 UART Data Register Empty SPI, STC Serial Transfer Complete
reti ;12 UART Tx Complete UART Rx Complete
reti ;13 Analog Comparator
reti ;14 Int2-Interrupt
reti ;15 Timer 0 Compare Match
reti ;16 EEPROM Ready
reti ;17 Store Program Memory Ready
RESET:
ldi r16, LOW(RAMEND) ;Stack initialisieren
out SPL, r16
ldi r16, HIGH(RAMEND)
out SPH, r16
ldi temp, (1<<ISC00)|(1<<ISC01)
out MCUCR, temp ;Interrupt INT0 konfiguriert
ldi temp, 1 << INTF0 ;InterruptFlagregister geloescht
out GIFR, temp
ldi temp, 1 << INT0 ;Interrupt INT0 aktiviert
out GICR, temp
clr Temp ;Temp mit 0b00000000 bzw. 0x00 laden
out DDRD, Temp ;PORTD als Eingang
ser Temp ;Temp mit 0b11111111 bzw. 0xFF laden
out PORTD, temp ;PullUp an PortD einschalten
out DDRB,Temp ;PORTB als Ausgang
out PORTB, temp ;PORTB (LEDs) aus
sei ;Interrupts zulassen
MAIN:
rcall TESTE
rjmp MAIN
TESTE:
push r16
in r16,SREG
push r16
clr temp ;loesche temp
inc temp ;increment von temp - "1"
cp Tast_Stat,temp ;ist TastStat = 1 dann Rufe Sub LED_AN auf, sonst ueberspringe naechsten Befehl
breq LED_AN
inc temp ;increment von temp - "2"
cp Tast_Stat,temp ;ist TastStat = 2 dann Rufe Sub LED_BLINK auf, sonst ueberspringe naechsten Befehl
breq LED_BLINK
inc temp ;increment von temp - "3"
cp Tast_Stat,temp ;ist TastStat = 3 dann Rufe Sub LED_AUS auf, sonst ueberspringe naechsten Befehl
breq LED_AUS
rjmp TESTE_EXIT
LED_AN: ;loesche temp
clr temp ;setze alle Bit in temp (0b00000000 bzw. 0x00)
out PORTB, temp ;Ausgabe an PortB
rjmp TESTE_EXIT
LED_BLINK:
in temp,PORTB ;lese PORTB in temp
com temp ;Einercomplement von temp (ist 0b00000000 > 0b11111111 oder umgekehrt)
out PORTB,temp ;Ausgabe an PortB
Tot_Zeit:
dec Delay ;zaehle ein Register R18 - 0b0000000 runter und springe danach aus der Schleife
brne Tot_Zeit
;dec Delay2 ;zaehle ein Register R19 - 0b0000000 runter und springe danach aus der Schleife
;brne Tot_Zeit
rjmp TESTE_EXIT
LED_AUS:
ser temp ;setze alle Bits in temp (0b11111111 bzw. 0xFF)
out PORTB,temp ;Ausgabe an PORTB
clr Tast_Stat ;Loesche Tast_Stat
sleep
rjmp TESTE_EXIT
TESTE_EXIT:
pop r16
out SREG,r16
pop r16
ret
INT0_ISR:
push R16 ;Inhalt von R16 auf Stack ablegen
in R16, SREG ;Statusregister in R16 lesen
push R16 ;Inhalt von R16(SREG) auf den Stack ablegen
inc Tast_Stat
pop R16 ;Ruecksichern von R16(SREG)
out SREG, R16 ;Ruecksichern von SREG
pop R16 ;Ruecksichern von R16
reti
Der 2. Tipp macht mir jedoch Kopfzerbrechen(Seite 5- TESTE_02 bzw. TESTE_03)
Beim Simulieren im AVR-Studio bekomme ich Speicherfehler, da das Programm den STACK durcheinander bringt...?)
Code:
;***** STK500 Lernprogramm Nr.3b
;*** Aufgabe: alle LEDs mit einem Taster auf dem STK500 schalten
;*** 1. Tastendruck: LEDs einschalten
;*** 2. Tastendruck: LEDs blinken
;*** 3. Tastendruck: LEDs ausschalten
;*** zum Entprellen soll ein Interrupt(Int0) benutzt werden
;***
.include "m8515def.inc"
.def Temp = r16 ; Temporary register
.def Tast_Stat = r17 ; Zaehler fuer Taste
.def Delay = R18 ; Wartezeit
.def Delay2 = R19 ; Wartezeit
;*****
;Reset and Interrupt vector ;VNr. Beschreibung
rjmp RESET ;1 POWER ON RESET
rjmp INT0_ISR ;2 Int0-Interrupt
reti ;3 Int1-Interrupt
reti ;4 TC1 Capture
reti ;5 TC1 Compare Match A TC2 Overflow
reti ;6 TC1 Compare Match B TC1 Capture
reti ;7 TC1 Overflow TC1 Compare Match A
reti ;8 TC0 Overflow TC1 Compare Match B
reti ;9 SPI, STC Serial Transfer Complete TC1 Overflow
reti ;10 UART Rx Complete TC0 Overflow
reti ;11 UART Data Register Empty SPI, STC Serial Transfer Complete
reti ;12 UART Tx Complete UART Rx Complete
reti ;13 Analog Comparator
reti ;14 Int2-Interrupt
reti ;15 Timer 0 Compare Match
reti ;16 EEPROM Ready
reti ;17 Store Program Memory Ready
RESET:
ldi r16, LOW(RAMEND) ;Stack initialisieren
out SPL, r16
ldi r16, HIGH(RAMEND)
out SPH, r16
ldi temp, (1<<ISC00)|(1<<ISC01)
out MCUCR, temp ;Interrupt INT0 konfiguriert
ldi temp, 1 << INTF0 ;InterruptFlagregister geloescht
out GIFR, temp
ldi temp, 1 << INT0 ;Interrupt INT0 aktiviert
out GICR, temp
clr Temp ;Temp mit 0b00000000 bzw. 0x00 laden
out DDRD, Temp ;PORTD als Eingang
ser Temp ;Temp mit 0b11111111 bzw. 0xFF laden
out PORTD, temp ;PullUp an PortD einschalten
out DDRB,Temp ;PORTB als Ausgang
out PORTB, temp ;PORTB (LEDs) aus
sei ;Interrupts zulassen
MAIN:
rcall TESTE
rjmp MAIN
TESTE:
push r16
in r16,SREG
push r16
; In Abhängigkeit von Tast_Stat Aktivität auswählen
clr temp ;
inc temp ; temp := Vergleichszahl; Anfangswert Eins
cp Tast_Stat,temp
brne TESTE_02 ; Sprung, wenn TastStat <> 1
rcall LED_EIN
rjmp TESTE_EXIT
TESTE_02:
; Tast_Stat > 1
inc temp
cp Tast_Stat,temp ; Vergleichszahl := 2
brne TESTE_03 ; Sprung, wenn TastStat <> 2
rcall LED_BLINK
rjmp TESTE_EXIT
TESTE_03:
; Tast_Stat > 3
inc temp ; Vergleichszahl := 3
cp Tast_Stat,temp
brne TESTE_EXIT ; Sprung, wenn TastStat <> 3
rcall LED_AUS
LED_EIN: ;loesche temp
clr temp ;setze alle Bit in temp (0b00000000 bzw. 0x00)
out PORTB, temp ;Ausgabe an PortB
rjmp TESTE_EXIT
LED_BLINK:
in temp,PORTB ;lese PORTB in temp
com temp ;Einercomplement von temp (ist 0b00000000 > 0b11111111 oder umgekehrt)
out PORTB,temp ;Ausgabe an PortB
;Tot_Zeit:
;dec Delay ;zaehle ein Register R18 - 0b0000000 runter und springe danach aus der Schleife
;brne Tot_Zeit
;dec Delay2 ;zaehle ein Register R19 - 0b0000000 runter und springe danach aus der Schleife
;brne Tot_Zeit
rjmp TESTE_EXIT
LED_AUS:
ser temp ;setze alle Bits in temp (0b11111111 bzw. 0xFF)
out PORTB,temp ;Ausgabe an PORTB
clr Tast_Stat ;Loesche Tast_Stat
rjmp TESTE_EXIT
TESTE_EXIT:
pop r16
out SREG,r16
pop r16
ret
INT0_ISR:
push R16 ;Inhalt von R16 auf Stack ablegen
in R16, SREG ;Statusregister in R16 lesen
push R16 ;Inhalt von R16(SREG) auf den Stack ablegen
inc Tast_Stat
pop R16 ;Ruecksichern von R16(SREG)
out SREG, R16 ;Ruecksichern von SREG
pop R16 ;Ruecksichern von R16
reti
eventuell habe ich auch einen Bug mit eingebaut.
Nach dem 1. Abarbeiten der ISR kommt das LED_EIN.
Hier wird wieder durch das rjmp der Programmzaehler auf den Stack abgelegt.
Danach der Sprung zum TESTE_EXIT.
Dabei wird ins SREG 0X00 (ein Teil vom Programmzaehler - rjmp LED_EIN) rein geschrieben.
-muesste da nicht doch LED_EIN mit „ret“ beendet werden?
Lesezeichen