so mal wieder was von mir ....
Wie schon angekuendigt, wollte ich ohne Interrupt ein Programmcode schreiben.
Dabei sollen die LEDs mit dem jeweils auf dem STK500 befindlichen Taster geschaltet werden.
Also druecke Taste - jeweilige LED wird je nach vorherigen Zustand umgeschaltet.
LED an wird LED aus
LED aus wird LED an
Ablauf:
Im Programm selbst frage ich in der MAIN den TastenPort ab und lese den Inhalt in ein 1 Register,
invertiere dieses und schiebe den Inhalt in ein 2. Register.
Teste dann ob Taste gedrueckt ist, wenn ja springe in Warte und zaehle dort ein Register runter,
danach(RE_TEST) lese erneut den TastenPort in das 1. Register aus invertiere den Inhalt,
vergleiche dann mit Inhalt des 2. Registers(erstes Auslesen), wenn gleich springe zu LED_TOGGLE.
In LED_TOGGLE wird der LED_PORT in das LED_Stat-Register gelesen.
Nun wird mittels Exklusiv-ODER das LED_Stat-Register mit dem TAST_Stat-Register umgeschrieben.
LED=1 Tast=1 == LED=0
LED=0 Tast=0 == LED=0
LED=0 Tast=1 == LED=1
LED=1 Tast=0 == LED=1
Dann wird der Inhalt des LED_Stat an den LED_PORT ausgegeben.
Als naechstes wird nun ueberprueft, ob die gedrueckte Taste noch immer gedrueckt ist.
Falls das sein sollte kommt der Sprung in eine Schleife, die permanent die Tasten abfragt, bis die urspruenglich gedrueckte Taste losgelassen wurde.
Wenn das passiert kommt der Sprung zurueck in die MAIN, wo das Spiel wieder von vorn beginnen kann.
Hier nun der Code...
Code:
;***** STK500 Lernprogramm Nr.4
;*** Aufgabe: die der jeweiligen Taste zugeordnete LED auf dem STK500 schalten
;*** 1. Tastendruck: LEDs einschalten
;*** 2. Tastendruck: LEDs ausschalten
;*** zum Entprellen soll kein Interrupt werden
;***
.include "m8515def.inc"
.def Temp = r16 ; Temporary register
.def Tast_Stat = r17 ; Tasten Status
.def Tast_Stat1 = r18
.def LED_Stat = R19 ; LED Status
;
.equ LED_PORT = PORTB ; LEDs
.equ LED_DDR = PORTB-1 ; DataDirectory fuer LEDs
.equ TAST_PORT= PORTD ; Tasten
.equ TAST_DDR = PORTD-1 ; DataDirectory fuer TastenEingang
.equ TAST_PIN = PORTD-2 ; TastenEingang
;
;*****
;Reset and Interrupt vector ;VNr. Beschreibung
rjmp RESET ;1 POWER ON RESET
reti ;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
clr Temp ;Temp mit 0b00000000 bzw. 0x00 laden
out TAST_DDR, Temp ;PORTD als Eingang
ser Temp ;Temp mit 0b11111111 bzw. 0xFF laden
out TAST_PIN, temp ;STK500 schaltet gegen GND - Taste gedreuckt (Pin==0)
out TAST_PORT, temp ;PullUp an PortD einschalten
out LED_DDR,Temp ;PORTB als Ausgang
out LED_PORT, temp ;PORTB (LEDs) aus
MAIN:
in Tast_Stat, TAST_PIN ; lese von PinD und speicher den Inhalt in Tast_Stat
com Tast_Stat ; invertiert fuer spaetere EOR-Berechnung
mov Tast_Stat1, Tast_Stat ; schiebe den Inhalt von Tast_Stat in Tast_Stat2
cpi Tast_Stat, 0b00000000 ; vergleiche Tast_Stat mit 0b00000000, wenn ungleich (Taste gedrueckt) springe zu
WARTE
brne WARTE
rjmp MAIN
WARTE:
push r25 ; Register auf Stack sichern
in r25, SREG
push r25
WARTE_0: ; Wartezeit zum Entprellen
dec r25 ; Schleife decrement Register 25
cpi r25, 0b00000000
breq WARTE_ZEIT_EXIT
rjmp WARTE_0
WARTE_ZEIT_EXIT: ; Ausgang aus Warteschleife
pop r25 ; Register vom Stack holen
out SREG, r25
pop r25
RE_TEST: ; 2. Test - Vergleich ob Taste noch immer gedrueckt
in Tast_Stat, TAST_PIN ; erneute Abfrage von Tasten und Vergleich mit erster Abfrage
com Tast_Stat ; invertiert fuer spaetere EOR-Berechnung
cp Tast_Stat, Tast_Stat1 ; wenn gleich, springe zu LED_TOGGLE
breq LED_TOGGLE
rjmp MAIN
LED_TOGGLE: ; schaltet LED um
in LED_Stat, LED_PORT ; lese LEDs aus und speichere in LED_Stat
eor LED_Stat, Tast_Stat ; ExclusivODER - schalte die Ausgaenge , wo Tasten gedrueckt werden um
; LED=1 Tast=1 == LED=0
; LED=0 Tast=0 == LED=0
; LED=0 Tast=1 == LED=1
; LED=1 Tast=0 == LED=1
out LED_PORT, LED_Stat
cp Tast_Stat, Tast_Stat1 ; vergleiche ob Taste losgelassen
breq WARTE2 ; wenn nicht losgelassen, springe in WARTE2
rjmp MAIN
; Abfrage von Tasten und Vergleich ob die urspruenglich gedrueckte Taste noch immer gedrueckt ist
; neu gedrueckte Taste wird waehrend die urspruenglich gedrueckte Taste noch gedrueckt ignoriert
; ist urspruenglich gedrueckte Taste gedrueckt wird die Schleife nicht verlassen
WARTE2:
RE_TEST_2:
in Tast_Stat, TAST_PIN
com Tast_Stat ; invertiert fuer spaetere EOR-Berechnung
and Tast_Stat, Tast_Stat1 ; Bitmaske - urspruenglich gedrueckte Taste
cp Tast_Stat, Tast_Stat1
breq WARTE2
rjmp MAIN
PS.
Einen Zustand habe ich nun noch nicht bedacht.
Es kann keine weitere Taste gedrueckt werden, solange die erste Taste nicht losgelassen wurde.
Das ist von mir in dem Programm zwar so gewollt, weil ich mir noch ueber die Ausfuehrung noch nicht Gedanken gemacht habe.
Haette ich das im jetzigen Code nicht verriegelt, wueder mir die weitere Taste, die erste LED wieder umschalten.
Eine Frage noch an die Experten:
Kann man im AVR-Studio die Zeilennummern aktivieren?
-> es macht die Fehlersuche leichter
Lesezeichen