Silvio,
ich habe mir das Lernprogramm 3c ungeändert aus Deinem Posting in den Simulator des AVRStudio geladen und durch alle Zustände von "Tast_Stat" durchlaufen lassen. Es hat einwandfrei funktioniert
. Nur die "sleep"-Anweisung war wirkungslos, weil Du im MCUCR-Register das Bit SE nicht auf "1" gesetzt hast. Aber selbst, wenn ich im Simulator SE in MCUCR auf "1" setze, läuft das Programm völlig richtig weiter.
Lernprogramm 3b muss noch korrigiert werden. Zweck der Übung war ja, die einzelnen Funktionen "LED_EIN", "LED_AUS" und "LED_BLINK" in je eine selbstständige Prozedur auszulagern. Wenn man das tut, muss man jede dieser Prozeduren auch mit einer eigenen "ret"-Anweisung abschliessen, sonst kommt der Stack tatsächlich durcheinander.
So könnte das aussehen
Code:
;***** STK500 Lernprogramm Nr.3bb
;*** 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
TESTE_EXIT:
pop r16
out SREG,r16
pop r16
ret
/*-----------------------
PROZEDUR LED_EIN
Die Prozedur LED_EIN setzt im Register "temp" alle Bits auf 0 und
gibt "temp" an PORTB aus.
Eingangsgrössen
temp enthält den aktuellen LED-Zustand
Ausgangsgrössen
temp enthält den LED-Zustand 0x00 = alle LEDs eingeschaltet
geänderte Register
temp
geänderte Ports
PORTB
*/
LED_EIN:
push r19
in r19,SREG
clr temp ;setze alle Bit in temp (0b00000000 bzw. 0x00)
out PORTB, temp ;Ausgabe an PortB
out SREG,r19
pop r19
ret
/*-----------------------
PROZEDUR LED_AUS
Die Prozedur LED_AUS setzt im Register "temp" alle Bits auf 1 und
gibt "temp" an PORTB aus.
Eingangsgrössen
temp enthält den aktuellen LED-Zustand
Ausgangsgrössen
temp enthält den LED-Zustand 0xFF = alle LEDs ausgeschaltet
geänderte Register
temp
geänderte Ports
PORTB
*/
LED_AUS:
push r19
in r19,SREG
ser temp ;setze alle Bits in temp (0b11111111 bzw. 0xFF)
out PORTB,temp ;Ausgabe an PORTB
clr Tast_Stat ;Loesche Tast_Stat
out SREG,r19
pop r19
ret
/*-----------------------
PROZEDUR LED_BLINK
Die Prozedur LED_BLINK invertiert im Register "temp" alle Bits und
gibt den neuen Inhalt von "temp" an PORTB aus.
Eingangsgrössen
temp enthält den aktuellen LED-Zustand
Ausgangsgrössen
temp enthält den invertierten LED-Zustand = alle LEDs umgeschaltet
geänderte Register
temp
geänderte Ports
PORTB
*/
LED_BLINK:
push r19
in r19,SREG
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
out SREG,r19
pop r19
ret
INT0_ISR:
push R19 ;Inhalt von R19 auf Stack ablegen
in R19, SREG ;Statusregister in R19 lesen
inc Tast_Stat
out SREG, R19 ;Ruecksichern von SREG
pop R19 ;Ruecksichern von R19
reti
So müsste es jetzt funktionieren.
Ciao,
mare_crisium
Lesezeichen