- Labornetzteil AliExpress         
Seite 2 von 14 ErsteErste 123412 ... LetzteLetzte
Ergebnis 11 bis 20 von 136

Thema: Anfänger mit STK500 und Assembler

  1. #11
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Anzeige

    Praxistest und DIY Projekte
    robo_wolf,

    meine Kommentare sind diesmal ein bisschen länglich ausgefallen , deshalb hab' ich sie als .pdf angehängt.

    Ciao,

    mare_crisium
    Angehängte Dateien Angehängte Dateien

  2. #12
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    55
    Beiträge
    310
    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 ###

  3. #13
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Buona sera, Silvio,

    freut mich, dass Du Dich trotz allem nicht vom Assembler-Programmieren abbringen lässt . Nur weiter so.

    Ciao,

    mare_crisium

  4. #14
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    55
    Beiträge
    310
    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?
    ### Silvio ###

  5. #15
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    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.

  6. #16
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    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

  7. #17
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    55
    Beiträge
    310

    Tasten_4

    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
    ### Silvio ###

  8. #18
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    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.
    Angehängte Dateien Angehängte Dateien

  9. #19
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    55
    Beiträge
    310
    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 ###

  10. #20
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    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

Seite 2 von 14 ErsteErste 123412 ... LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress