-         

Seite 1 von 14 12311 ... LetzteLetzte
Ergebnis 1 bis 10 von 136

Thema: Anfänger mit STK500 und Assembler

  1. #1
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    48
    Beiträge
    310

    Anfänger mit STK500 und Assembler

    Anzeige

    Hallo Leute,
    beschäftige mich mit der Programmierung des STK500 mit Assembler.
    Naja vielleicht sollte ich lieber schreiben, ein Newbi möchte sich mit der Assemblerprogrammierung des STK500 beschäftigen.
    Als Software benutze ich die mitgelieferte AVR-Studio.
    Habe im Vorfeld schon einiges in Foren und Büchern gelesen.
    So als Einstieg und zum besseren Erlernen möchte ich mir kleine Aufgaben stellen und diese dann umsetzen.
    Den Code werde ich hier posten und wäre sehr an euren Meinungen, Vorschlägen und Kritiken interessiert.
    Zu den Code werde ich immer Kommentare anfügen, damit man versteht was ich damit bezwecke.
    Anfangen möchte ich mit einer einfachen Tastenschaltung.
    Bei dieser sollen die 8 LEDs des STK500 mit einer Taste entprellt an- bzw. ausgeschaltet werden.
    Das STK500 habe ich mit einen ATMega8515 bestückt. PORTB ist mit den Tastern und PORTD mit den LEDs verbunden.
    Code:
    ;***** STK500 Lernprogramm 
    ;*** Aufgabe: alle LEDs mit einem Taster auf dem STK500 an bzw. ausschalten
    ;*** zum Entprellen soll ein Interrupt(Int0) benutzt werden 
    ;***
    .include "m8515def.inc"
    .def Temp      = r16 				; Temporary register
    .def LED_STAT  = r17				; LED sind mit PortB verbunden
    ;***** 
    ;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 << INT0				;Interrupt INT0 aktiviert
        out GICR, temp					
    
    	ldi temp, 1 << ISC00			;Interrupt INT0 konfiguriert
    	ori temp, 1 << ISC01
    	out MCUCR, 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:
    
        rjmp MAIN     					;Die Schleife ruft mit dem Sprungbefehl
                                		;rjmp sich ständig selbst auf.(endlos) 
                                
    
    INT0_ISR:
    	cli								;Interrupts sperren
    	in LED_STAT, PORTB				;PORTB auslesen in LED_STAT
    	com LED_STAT					;Invertieren von LED_STAT
    	out PORTB, LED_STAT				;Ausgabe von temp an PORTB -> LEDs aus
    	reti
    Das Programm habe ich zum STK500 übertragen und tut auch das was es soll.
    ### Silvio ###

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    robo_wolf,

    da hast Du Dir einen sehr guten und erfolgsversprechenden Zugang ausgesucht ! Ein paar Anmerkungen zu Deinem Programm:

    Du musst bedenken, dass die Interrupt-Dienstprozedur INT0_ISR dieselben Register verwendet, wie das Hauptprogramm. Wenn also die Haupschleife MAIN mit bestimmten Registern etwas ausrechnen wollte, als der Interrupt sie unterbrach, dann erwartet sie, dass die Register bei der Rückkehr aus dem Interrupt wieder dieselben Werte haben wie vorher. Du musst also dafür sorgen, dass die Registerinhalte gleich zu Beginn von INT0_ISR auf den Stack gesichert (push rxx) und unmittelbar vor der Rückkehr (reti) wiederhergestellt (pop rxx) werden. Wichtig ist auch, den aktuellen Inhalt des SREG auf dem Stack zu sichern. Sonst gehen dem Hauptprogramm so wichtige Sachen wie der aktuelle Stand des Carry- oder Zero-Flags verloren. Also brauchst Du parallel zum Sichern der Register noch die Zeilen

    Aus leidvoller () Erfahrung habe ich mir angewöhnt, vor jedem Unterprogramm und jedem Interruptdienst aufzuschreiben, welche Register wie verwendet werden. Z.B. so:

    Code:
    /*
    Der Steuerblock und die Daten der FIFO werden im RAM angelegt.
    Die Offsets der Steuerdaten sind
     +0 : FIFO_FLAGS
     +1 : FIFO_WR	zeigt auf nächste Schreibposition
     +2 : FIFO_RD	zeigt auf nächste Leseposition
     +3 : FIFO_CAP	FIFO-Kapazität, maximal 255 Byte
     Datenblock:
     +4 : <1. Datenbyte>
    
    Die Bedeutung der Bits in  FIFO_FLAGS ist:
    XXXX XXXX
           ||
           |+------ 0: FIFO ist nicht voll
           |		1: FIFO ist voll		
           |
           +------- 0: FIFO ist nicht leer
           			1: FIFO ist leer
    
    */
    
    ;------------------------------------------	
    ;
    ;	FIFO-KONSTANTEN
    ;
    ; BYTE-OFFSETs
    
    .equ FIFO_FLAGS = 0
    .equ FIFO_WR	= 1	; zeigt auf nächste freie Position
    .equ FIFO_RD	= 2	; zeigt auf nächste belegte Position
    .equ FIFO_CAP	= 3	; 
    
    .equ FIFO_LNG	= 4	; Länge des Datenblocks
    
    ;BIT-OFFSETs
    .equ FIFO_VOLL	= 0
    .equ FIFO_LEER	= 1	; 
    			; Der Platzbedarf im RAM
    			; berechnet sich als
    			; FIFO_SIZE = FIFO_LNG + FIFO_CAP
    
    /*------------------------------------------	
    
     	PROCEDURE FIFO8_CREATE
    
     erzeugt die Struktur einer leeren FIFO für 1-Byte-Daten im RAM 
    
     Eingangsvariablen
    	zh:zl:   enhält den Zeiger auf die RAM-Adresse,
    	     an der die FIFO angelegt werden soll
    	r16: enthält die FIFO-Kapazität
    
    
     Ausgangsvariablen
    	zh:zl : enthält den Zeiger auf die FIFO
    	r16: enthält die FIFO-Kapazität
    
     geänderte Register
    	keine
    
     geänderte Ports
    	keine
    */
    
    FIFO8_CREATE: 
    	push r17
    	in r17,SREG
    	push r17
    	push r18
    
    ; FIFO-Steuerblock mit Nullen füllen
    	ldi r18,FIFO_LNG
    	clr r17
    
    FIFO_CREAT01:
    	tst r18
    	breq FIFO_CREAT_00
    	st z+,r17
    	dec r18
    	rjmp FIFO_CREAT01
    
    FIFO_CREAT_00:	
    ; zh:zl wieder auf Anfang der FIFO stellen
    	sbiw zh:zl,FIFO_LNG
    
    ; Anfangszustand der Flags einstellen 	
    	ldi r17,(1<<FIFO_LEER); Flag "FIFO_LEER" setzen
    	std z+FIFO_FLAGS,r17
    	dec r16			;
    	std z+FIFO_CAP,r16 ; FIFO-Kapazität speichern 
    	inc r16			;
    
    	pop r18
    	pop r17
    	out SREG,r17
    	pop r17
    	ret
    Weiterhin viel Spass und viel Erfolg!

    mare_crisium

  3. #3
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    48
    Beiträge
    310

    verstehe ich das so richtig?

    Hallo mare_crisium,
    habe mein Listing angepasst.
    Beim Testen im Simulator habe ich mir den Datenspeicher mit als Fenter anzeigen lassen und den Verlauf verglichen.
    Das erste was nach Eintreten der ISR auf den Stack kommt ist der Programmcounter(zaehler). Dann werden die Registerinhalte, wie ich sie sichere, nach unten gestapelt und spaeter wieder ausgelesen.
    Die Speicherinhalte vom Datenspeicher bleiben bestehen, bis sie von erneuten Aufrufen der ISR ggf. ueberschrieben werden.

    Code:
    ;***** STK500 Lernprogramm 
    ;*** Aufgabe: alle LEDs mit einem Taster auf dem STK500 an bzw. ausschalten 
    ;*** zum Entprellen soll ein Interrupt(Int0) benutzt werden 
    ;*** 
    .include "m8515def.inc" 
    .def Temp      = r16             ; Temporary register 
    .def LED_STAT  = r17            ; LED sind mit PortB verbunden 
    ;***** 
    ;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 << INT0        ;Interrupt INT0 aktiviert 
        out GICR, temp                
    
       ldi temp, 1 << ISC00        ;Interrupt INT0 konfiguriert 
       ori temp, 1 << ISC01 
       out MCUCR, 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: 
    
        rjmp MAIN                  ;Die Schleife ruft mit dem Sprungbefehl 
                                   ;rjmp sich ständig selbst auf.(endlos) 
                                
    
    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 
    	push R17					;Inhalt von R17 auf den Stack ablegen
    
        cli                         ;Interrupts sperren 
    
        in LED_STAT, PORTB          ;PORTB auslesen in LED_STAT 
        com LED_STAT                ;Invertieren von LED_STAT 
        out PORTB, LED_STAT         ;Ausgabe von LED_STAT an PORTB -> LEDs an bzw. aus
    
    	pop R17						;Ruecksichern von R17
    	pop R16						;Ruecksichern von R16(SREG)
    	out SREG, R16				;Ruecksichern von SREG
    	pop R16
    		 
        reti
    ### Silvio ###

  4. #4
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    So wie gezeigt ist das retten der Register schon richtig. In diesem Speziellen Fall, wo im Hauptprogramm nichts wirkliches passiert, kann man auch außnahmsweise mal auf das sichern des SREG verzichten.
    Das erste Programm war also schon OK, aber man sollte sich das sichern der Register ruhig angewöhnen.

    In ASM ist es ein gar nicht so seltener Trick einfach ein paar Register für die Benutzung im Interrupt zu reservieren, dass spart einem das sichern der Register. Oft nutzt man ja ASM gerade deshalb man das maximale an Geschwindigkeit haben will.


    Es ist sonst recht hilfreich wenn man oben als Kommentar reinschreibt zu welcher Hardware das Programm gehört. Also wo hängen Taster oder LEDs dran. Für So einen kleinen Test gehts noch ohne, später sollte das aber dazu.

    Ist nur eine Kleinigkeit, aber beim konfigurieren des Interrupts sollte man erst die Einstellungen (Flanke etc.) machen, dann ggf. das Interruptflag löschen, und erst dann den Interrupt einschalten. Sonst gibt es auch mal einen ungeplanten Interrupt vom Konfigurieren.

  5. #5
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    48
    Beiträge
    310

    Interrupt Flag loeschen

    Hallo Besserwessi,
    erstmal vielen Dank fuer die Tipps...
    Habe nun den Code wie folgt abgeaendert.
    Code:
    ;***** STK500 Lernprogramm 
    ;*** Aufgabe: alle LEDs mit einem Taster auf dem STK500 an bzw. ausschalten 
    ;*** zum Entprellen soll ein Interrupt(Int0) benutzt werden 
    ;*** 
    .include "m8515def.inc" 
    .def Temp      = r16             ; Temporary register 
    .def LED_STAT  = r17            ; LED sind mit PortB verbunden 
    ;***** 
    ;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        ;Interrupt INT0 konfiguriert 
    	ori temp, 1 << ISC01 
    	out MCUCR, temp 
    
    	ldi temp, 0 << 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: 
    
        rjmp MAIN                  ;Die Schleife ruft mit dem Sprungbefehl 
                                   ;rjmp sich ständig selbst auf.(endlos) 
                                
    
    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 
    	push R17					;Inhalt von R17 auf den Stack ablegen
    
         in LED_STAT, PORTB          ;PORTB auslesen in LED_STAT 
        com LED_STAT                ;Invertieren von LED_STAT 
        out PORTB, LED_STAT         ;Ausgabe von LED_STAT an PORTB -> LEDs an bzw. aus
    
    	pop R17						;Ruecksichern von R17
    	pop R16						;Ruecksichern von R16(SREG)
    	out SREG, R16				;Ruecksichern von SREG
    	pop R16
    		 
        reti
    Reihenfolge Konfiguration und Aktivierung des INT0, sowie das Loeschen des INTF0 im GIFR.
    Kannst Du mir naeheres zu den Flags sagen?
    Ach ja das CLI in der ISR habe ich entfernt, da es automatisch geschieht.

    werde ueber Weihnachten nicht zu Haus sein und somit auch nicht antworten koennen.
    ### Silvio ###

  6. #6
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Die Reihenfolge bei der Konfiguration des Interrupts ist schon OK.

    Allerdings haben die Register mit den Interruptflags eine komische Eigenschaft. Um da ein Bit zu löschen muß man eine 1 reinschreiben.
    Das klingt erstmal widersinnig, erlaubt aber so ein direktes und atomares löschen einzelner Bits. Außerden kann man so oft den gleichen Wert zulöschen der Flags reinschreiben. Die Bits haben nämlich sinnigerweise die gleiche Reihenfolge.
    kurz gesagt: 0 << INTF0 ist falsch.

    Selbst wenn man ein normales Bit löschen wollte, ist das eine umständliche Schreibweise für 0. Man löscht also normal alle Bits, nur nicht grade bei den Interuptflags.

    Die beiden Bits für die Interrupt-konfiguration kann man übrigens auch gleich zusammenfügen, das muß man nicht erst zur Laufzeit machen.
    Also statt:
    ldi temp, 1 << ISC00 ;Interrupt INT0 konfiguriert
    ori temp, 1 << ISC01
    kürzer
    ldi temp, (1 << ISC00) |(1 << ISC01) ;Interrupt INT0 konfiguriert

  7. #7
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    48
    Beiträge
    310
    Hallo Besserwessi,
    bist ja noch spät bzw. schon frueh unterwegs.
    Hier wieder eine angepasste Version des Codes:
    Code:
    
    
    ;***** STK500 Lernprogramm 
    ;*** Aufgabe: alle LEDs mit einem Taster auf dem STK500 an bzw. ausschalten 
    ;*** zum Entprellen soll ein Interrupt(Int0) benutzt werden 
    ;*** 
    .include "m8515def.inc" 
    .def Temp      = r16             ; Temporary register 
    .def LED_STAT  = r17            ; LED sind mit PortB verbunden 
    ;***** 
    ;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)        ;Interrupt INT0 konfiguriert 
    	out MCUCR, temp 
    
    	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: 
    
        rjmp MAIN                  ;Die Schleife ruft mit dem Sprungbefehl 
                                   ;rjmp sich ständig selbst auf.(endlos) 
                                
    
    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 
    	push R17					;Inhalt von R17 auf den Stack ablegen
    
         in LED_STAT, PORTB          ;PORTB auslesen in LED_STAT 
        com LED_STAT                ;Invertieren von LED_STAT 
        out PORTB, LED_STAT         ;Ausgabe von LED_STAT an PORTB -> LEDs an bzw. aus
    
    	pop R17						;Ruecksichern von R17
    	pop R16						;Ruecksichern von R16(SREG)
    	out SREG, R16				;Ruecksichern von SREG
    	pop R16
    		 
        reti

    --- werde ueber Weihnachten nicht zu Haus sein und somit auch nicht antworten koennen ---
    ### Silvio ###

  8. #8
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    48
    Beiträge
    310

    Teil 2

    so habe nun ein weiteres Miniprogramm.
    diesmal mit Ein und Austaster
    Code:
    ;***** STK500 Lernprogramm Nr.2
    ;*** Aufgabe: alle LEDs mit einem Taster auf dem STK500 an ubd mit einem 2. Taster ausschalten 
    ;*** zum Entprellen sollen Interrupts(INT0 und INT1) benutzt werden 
    ;*** 
    .include "m8515def.inc" 
    .def Temp      = r16            ; Temporary register 
    
    ;***** 
    ;Reset and Interrupt vector         ;VNr.  Beschreibung 
       rjmp   RESET                ;1   POWER ON RESET 
       rjmp   INT0_ISR             ;2   Int0-Interrupt 
       rjmp   INT1_ISR             ;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, temp
    	ldi r16, HIGH(RAMEND) 
    	out SPH, temp
    
    	ldi temp, (1<<ISC00)|(1<<ISC01)|(1<<ISC10)|(1<<ISC11)
    	out MCUCR, temp 			;Interrupt INT0 und INT1 konfiguriert 
    
    	ldi temp, (1<<INTF0)|(1<<INTF1)
    	out GIFR, temp				;InterruptFlagregister geloescht 
    
    	ldi temp, (1<<INT0)|(1<<INT1)
    	out GICR, temp				;Interrupt INT0 und INT1 aktiviert                 
    
      
    	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: 
    
        rjmp MAIN                  ;Die Schleife ruft mit dem Sprungbefehl 
                                   ;rjmp sich ständig selbst auf.(endlos) 
                                
    
    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 
    
    	ser Temp                    ;Temp mit 0b11111111 bzw. 0xFF laden 
        out PORTB, temp		        ;Ausgabe an PORTB -> LEDs aus
    
    	pop R16						;Ruecksichern von R16(SREG)
    	out SREG, R16				;Ruecksichern von SREG
    	pop R16
    		 
        reti 
    
    INT1_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 
    
    	clr Temp                    ;Temp mit 0b00000000 bzw. 0x00 laden 
        out PORTB, temp         	;Ausgabe von LED_STAT an PORTB -> LEDs an
    
    	pop R16						;Ruecksichern von R16(SREG)
    	out SREG, R16				;Ruecksichern von SREG
    	pop R16
    		 
        reti
    ### Silvio ###

  9. #9
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    robo_wolf,

    als Folgeaufgabe böte sich Folgendes an:
    Ein allgemein anwendbares Entprellverfahren. So wie Du's jetzt machst, kannst Du immer nur maximal zwei Taster entprellen, die obendrein auch noch die beiden wertvollen externen Interrupts belegen. Deshalb ist ein Verfahren sehr nützlich, mit dem Taster entprellt werden, die einfach an einen Input-Port angeschlossen sind. Dabei kannst Du auch gleich die ersten Schritte mit Timer/Countern machen.

    Code:
    ;***** STK500 Lernprogramm Nr.3
    ;*** Aufgabe: alle LEDs mit einem Taster auf dem STK500 an und mit einem 2. Taster ausschalten
    ;*** zum Entprellen wird Timer/Counter0 genutzt. 
    ; Die Interrupts INT0 und INT1 werden nicht benutzt. Der Overflow-Interrupt des TimerCounter0 
    ; wird aktiviert. 
    ; Bei jedem TOV0-Interrupt wird der Zustand von Taster0 und Taster1 abgelesen. 
    ; Für jeden Taster wird ein Zustandsregister eingerichtet. Wenn bei einer Ablesung Taster0 
    ; gedrückt ist, wird in das Zustandsregister von Taster0 von links eine 1 eingeschoben 
    ; (z.B. <ror>-Anweisung, vorher CARRY-Flag setzen). Wenn bei einer Ablesung Taster0 nicht
    ; gedrückt ist, wird in das Register von rechts eine Null  eingeschoben. Die Taste gilt nur dann als gedrückt,
    ; wenn der Inhalt des Registers grösser als 0x0F ist.
    ; Das Entprellen bei Taster1 wird analog gelöst. 
    ;
    ; Mit dem Prescaler spielen, um verschiedene Reaktionsgeschwindigkeiten auzuprobieren
    ; Mit dem Schaltgrenzwert des Zustandsregisters spielen, um zeitlich symmetrisches und
    ; unsymmetrisches Verhalten zu erproben
    ;***
    Wär' das was? Weiterhin viel Spass beim Assemblern !

    mare_crisium

  10. #10
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    48
    Beiträge
    310
    hallo mare_crisium,
    klar doch wollte eh das Programm abaendern, dass jeder Taster verwendet werden kann. Somit muss ich mich um ein anderes entprellen kuemmern.
    Aber eine Schaltung habe ich noch zwischenzeitlich gemacht.
    Angelehnt an das Hundegeschirr von unseren Berner.
    hier dieser Code:
    Code:
    
    ;***** STK500 Lernprogramm Nr.3
    ;*** 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)|(1<<SE)        
    	out MCUCR, temp 			;Interrupt INT0 und Sleep enable 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:
    	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
    	sleep
    	ret            
    
    		LED_AN:							;loesche temp
    			clr temp					;setze alle Bit in temp (0b00000000 bzw. 0x00)
    			out PORTB, temp				;Ausgabe an PortB
    			sleep
    			ret
    
    		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
    			ret
    
    		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
    			ret
    
    
    
    INT0_ISR: 
    	ldi Delay, 0b00000001		;Ruecksprung aus LED_BLINK beschleunigen
    	ldi Delay2, 0b00000001		;Ruecksprung aus LED_BLINK beschleunigen
    	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
    Als naechstes wird das generelle entprelle in Angriff genommen
    ### Silvio ###

Seite 1 von 14 12311 ... LetzteLetzte

Berechtigungen

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