Werbung
Hallo mare_crisium,
was soll ich sagen...
Als ich heute Deine Kommentare gelesen habe, war ich so richtig "baff" und andererseits wahnsinnig froh, dass Du Dir so viel Zeit genommen hast, mir Erklaerungen und Beispiele fuer mein kleines Programm zu schreiben. Dafuer erst einmal vielen vielen Dank.
Die "ret" Erklaerung sehe ich nun auch von anderen Blickpunkt aus. Habe beim Erstellen des Codes an der Art nach sich ziehende Probleme nicht gedacht.
Man lernt halt nur aus solchen "Fehlern", wenn man sie bewusst gemacht hat.
Die Delays auf 1 zusetzen kam eigentlich nur aus dem Studio-Simulator.
Dort hatte ich gesehen, dass beim Ruechsprung aus der ISR(wenn ISR waehrend LED_BLINK ausgefuehrt wurde) erst noch die Tot_Zeit abgearbeitet wurde, bevor es zu TESTE zurueck "ret" geht.
Naja ich gebe es zu, da hatte ich schon gemerkt, dass der Code nicht ganz so war, wie ich es eigentlich wollte.
Sah aber zu dem Zeitpunkt keinen anderen Weg, das Runterzaehlen der Register zu beschleuigen oder gar zu unterbinden.
Seit meinem letzten Posting hatte ich leider nicht so viel Zeit, wie ich gern wollte.
Hatte mich aber schon an das naechste Programm, wie von Dir vorgeschlagen, die Tasten ohne Interrupt zu entprellen gemacht und da ein wenig probiert.
Das muss ich nun auch noch einmal gruendlich ueberdenken bzw ueberarbeiten.
Zuvor moechte ich mir Deine Codeaenderungen im Simulator genau anschauen.
Habe da sicher noch einige Fragen....![]()
### Silvio ###
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:
Der 2. Tipp macht mir jedoch Kopfzerbrechen(Seite 5- TESTE_02 bzw. TESTE_03)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
Beim Simulieren im AVR-Studio bekomme ich Speicherfehler, da das Programm den STACK durcheinander bringt...?)
eventuell habe ich auch einen Bug mit eingebaut.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
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?
### Silvio ###
Das sichern des SREG und ggf, anderer register braucht man nur für ISRs.
Wenn man es trotzdem macht, verschwendet man erstmal Platz auf den Stack, und man kann leicht Fehler machen sodass es dann den Stack richtig durcheinander bringt.
Dann ist da noch ein Fehler dirn: Unterprogramme die man mir Rcall aufruft, bendet man mit RET, nicht mit einem RJMP nach teste_exit.
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
So müsste es jetzt funktionieren.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
Ciao,
mare_crisium
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...
PS.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
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
### Silvio ###
robo_wolf,
als erstes fiel mir am Lernprogramm Nr. 4 auf, dass Du nach dem Label 'WARTE' diese "push"-Anweisungen eingebaut hast. Die brauchst Du gar nicht. Auf die Gefahr hin, Dir nichts Neues zu erzählen, habe ich trotzdem 'mal ein paar Erklärungen zum Stack und zu den "call"-, "ret"-, "push"- und "pop"-Anweisungen aufgeschrieben. Es kann ja nicht schaden ....
Den Rest Deines Programms kommentiere ich später.
mare_crisium
P.S.: Ich hab's bisher noch nicht hingekriegt, die Zeilennummern anzeigen zu lassen. Ich habe mich bisher immer mit der kleinen Anzeige unten rechts beholfen, die die Zeilennummer beim Cursor angibt.
Hallo mare_crisium,
vielen Dank für doch sehr ausfuehrliche Erlaeuterung des Stacks.
Sicher war mir die Funktion und Arbeitsweise schon vertraut.Trotzdem fand ich die Erklaerungen noch vertiefend und leicht verstaendlich.
Aber auch andere User lesen unsere Zeilen und werden sicher ueber so manche verstaendlich geschriebene Erlaeuterung dankbar sein.
Jetzt wo Du mich darauf aufmerksam gemacht hast, sehe ich auch, dass keine Subs im Programm 4 vorhanden sind. Will das Programm eh noch erweitern und eventuell etwas umstellen... Da werde ich doch wieder Unterprogramme mit verwenden.
### Silvio ###
Danke für Deinen freundlichen Kommentar, robo_wolf. Leider interessieren sich nicht mehr sehr viele für Assemblerprogrammierung, wie man an der Anzahl downloads sieht. C und Konsorten führen halt viel schneller zu sichtbaren Erfolgen; Assembler erfordert Geduld und Übung. Beides ist hierzulande jüngst etwas aus der Mode gekommen.
Wenn Du sowieso noch einmal Hand an Dein Programm Nr. 4 legen willst, wie wär's, wenn Du versuchtest, die Tasten von einem Dienstprogramm ablesen zu lassen, dass in regelmässigen Abständen von einem Timer-Interrupt ausgelöst wird? Die Timer wirst Du noch sehr häufig brauchen. Je früher Du Dich mit denen anfreundest, desto besser!
Ciao,
mare_crisium
Lesezeichen