PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Interrupt Routine



Saturas077
22.04.2014, 22:13
Hallo Guten Nabend,

Ich steige von C auf Assembler um und verstehe hier was nicht.

Viele Tutorials gibt es zu Assembler AVR nicht, die nicht kopiert worden sind.
Ich habe alles ausprobiert was ich in irgendwelchen Anleitungen und Tutorials fand.
Die Interrupt Vectoren per .org, weglassen, mit reti, etwas gemischt....
Das Handbuch über den Atmega 8 sagt:


When the SREG I-bit, TOIE0 (Timer/Counter0 Overflow
Interrupt Enable), and TOV0 are set (one), the Timer/Counter0 Overflow interrupt is executed.

Genau dieser Zustand tritt auch in der Simulation von Atmel Studio 6.2 ein.
Allerdings wird dann nicht die Routine ausgeführt, es wird nichts zurück gesetzt...
Ich komme mit den Tutorials und meinem eigenen Latein nicht mehr weiter und hoffe ihr könnt mich auf den rechten Pfad zurück bringen.
Mein Übungscode sieht wie folgt aus:



.include "m8def.inc"

rjmp main ; Reset Handler
reti ; IRQ0 Handler
reti ; IRQ1 Handler
reti ; Timer2 Compare Handler
reti ; Timer2 Overflow Handler
reti ; Timer1 Capture Handler
reti ; Timer1 CompareA Handler
reti ; Timer1 CompareB Handler
reti ; Timer1 Overflow Handler
rjmp interrupt ; Timer0 Overflow Handler
reti ; SPI Transfer Complete Handler
reti ; USART RX Complete Handler
reti ; UDR Empty Handler
reti ; USART TX Complete Handler
reti ; ADC Conversion Complete Handler
reti ; EEPROM Ready Handler
reti ; Analog Comparator Handler
reti ; Two-wire Serial Interface Handler
reti ; Store Program Memory Ready Handler


main:
;Initializiere Stackpointer

ldi r17, HIGH(RAMEND)
out SPH, r17
ldi r17, LOW(RAMEND)
out SPL, r17
sei

ldi r17, 0xFF ;setze B als Ausgang
out DDRB, r16

ldi r16, 0x01 ; setze Pin 1 als High.

ldi r17, (1<<CS00) ; Setze Vorteiler
out TCCR0, r16
ldi r17, (1<<TOIE0) ; Setze Overflow Interrupt
out TIMSK, r16

loop:
rjmp loop ; Ewiger Loop

interrupt:
out PORTB, r16
com r16
reti

Searcher
23.04.2014, 06:30
When the SREG I-bit, TOIE0 (Timer/Counter0 Overflow
Interrupt Enable), and TOV0 are set (one), the Timer/Counter0 Overflow interrupt is executed.
Genau dieser Zustand tritt auch in der Simulation von Atmega 6.2 ein.
Allerdings wird dann nicht die Routine ausgeführt,es wird nichts zurück gesetzt...

Was soll Atmega 6.2 sein? Was soll den das Programm machen und was meinst Du mit "es wird nichts zurück gesetzt..."?

Ich habe keinen Simulator für Dein Programm installiert und bin nur gedanklich durchgegangen:
Meiner Meinung nach sollte die ISR schon ausgeführt werden allerdings wird PORTB nicht auf Ausgang geschaltet und die Konfiguration von Interrupt und Vorteiler scheint mir eher zufällig zu klappen.
Hab Deinen Code kopiert und mit weiteren Kommentaren versehen:


.include "m8def.inc"

rjmp main ; Reset Handler
reti ; IRQ0 Handler
reti ; IRQ1 Handler
reti ; Timer2 Compare Handler
reti ; Timer2 Overflow Handler
reti ; Timer1 Capture Handler
reti ; Timer1 CompareA Handler
reti ; Timer1 CompareB Handler
reti ; Timer1 Overflow Handler
rjmp interrupt ; Timer0 Overflow Handler
reti ; SPI Transfer Complete Handler
reti ; USART RX Complete Handler
reti ; UDR Empty Handler
reti ; USART TX Complete Handler
reti ; ADC Conversion Complete Handler
reti ; EEPROM Ready Handler
reti ; Analog Comparator Handler
reti ; Two-wire Serial Interface Handler
reti ; Store Program Memory Ready Handler

main:
;Initializiere Stackpointer

ldi r17, HIGH(RAMEND)
out SPH, r17
ldi r17, LOW(RAMEND)
out SPL, r17
sei

ldi r17, 0xFF ;setze B als Ausgang (alle Bits in r17 werden gesetzt)
out DDRB, r16 (r16 ist nicht initialisiert und wird defaultmäßig 0x00 enthalten
Ausgabe nach DDRB wird keinen einen Effekt haben, PORTB bleibt auf Eingang)

ldi r16, 0x01 ; setze Pin 1 als High. (Bit 0 in R16 wird gesetzt)

ldi r17, (1<<CS00) ; Setze Vorteiler (Bit 0 in r17 wird gesetzt, alle anderen gelöscht)
out TCCR0, r16 (r16 soll den Vorteiler setzen? Soll nicht r17 nach TCCR0 ausgegeben werden?)
ldi r17, (1<<TOIE0) ; Setze Overflow Interrupt (Bitnummer von TOIE0 wird in r17 gesetzt - Maske für TIMSK?)
out TIMSK, r16 (r16 wird nach TIMSK geschrieben. Sollte das nicht r17 sein?)

loop:
rjmp loop ; Ewiger Loop

interrupt:
out PORTB, r16 (r16 hat beim ersten interrupt noch Bit 0 gesetzt
und schaltet hier nur den Pullup für PB0 ein, da PORTB noch auf
defaultmaessigem Eingang ist, siehe oben)
(beim zweiten Interrupt wird Pullup für PB0 wieder ausgeschaltet und
und für alle anderen Pins auf PORTB eingeschaltet)
(Nur die Pullups werden getoggelt wg. nachfolgendem COM r16)
com r16 (alle Bits in R16 werden invertiert und SREG verändert)
reti

Gruß
Searcher

Saturas077
23.04.2014, 07:12
Ich danke dir für deine schnelle Ausführung Searcher.

Ich meinte selbstverständlich Atmel Studio 6.2, das Programm soll rein dazu dienen mir im Simulator anzuschauen wie die Interruptroutine angesprungen wird.
Das die falschen Register im out stehen, liegt daran das ich gestern die einmal anders angeordnet hatte, hatte zuvor nur das Register 16 benutzt. Leider habe ich den Wald vor...

Der Simulator macht eigentlich genau das was ich mir auch im Kopf vorgestellt habe.
Hier nochmal der Code:


.include "m8def.inc"

rjmp main ; Reset Handler (Hier sollte das Programm direkt zum main target springen! TUT er auch.)
reti ; IRQ0 Handler (Schaut sich das Programm nicht mehr an)
reti ; IRQ1 Handler
reti ; Timer2 Compare Handler
reti ; Timer2 Overflow Handler
reti ; Timer1 Capture Handler
reti ; Timer1 CompareA Handler
reti ; Timer1 CompareB Handler
reti ; Timer1 Overflow Handler
rjmp interrupt ; Timer0 Overflow Handler
reti ; SPI Transfer Complete Handler
reti ; USART RX Complete Handler
reti ; UDR Empty Handler
reti ; USART TX Complete Handler
reti ; ADC Conversion Complete Handler
reti ; EEPROM Ready Handler
reti ; Analog Comparator Handler
reti ; Two-wire Serial Interface Handler
reti ; Store Program Memory Ready Handler


main:
;Initializiere Stackpointer

ldi r17, HIGH(RAMEND)
out SPH, r17
ldi r17, LOW(RAMEND)
out SPL, r17
sei

ldi r16, 0xFF ;setze B als Ausgang
out DDRB, r16

ldi r16, 0x01 ; setze Pin 1 als High.

ldi r17, (1<<CS00)
out TCCR0, r17
ldi r17, (1<<TOIE0)
out TIMSK, r17

loop:
rjmp loop (Hängt dann hier fest obwohl TOV0 und TOIE0 ausgelöst wurden. I Bit ist gesetzt durch sei)

interrupt:
out PORTB, r16
com r16
ret


Die zwei () Kommentare sind meine Meinungen, was das Programm tut und was es wirklich macht.

Searcher
23.04.2014, 07:24
interrupt:
out PORTB, r16
com r16
ret



Hi, böse Falle oder nur Tippfehler?
Es muß RETI und nicht nur RET sein.

Gruß
Searcher

Saturas077
23.04.2014, 07:40
Hallo,
habe beides Ausprobiert, aber dachte mir das reti richtiger sei.

Trotz deiner Anmerkungen keine Funktion. :/
Gruß

Searcher
23.04.2014, 07:58
Es muß RETI sein. Sonst wird das Global Interrupt Enable Bit in SREG nicht mehr gesetzt, daß ja zur Ausführung der ISR vom µC gelöscht wurde. Effekt: Interrupt tritt nur einmal auf und dann nicht mehr.


Trotz deiner Anmerkungen keine Funktion. :/

Keine Funktion (Invertieren der Bits im PORTB?) im Simulator? Woran erkennst Du das? Keine Funktion im Atmega (LEDs, Oszilloskop). Liegts am Simulator (kann ich selbst nicht testen)?

Mit welchem Takt läuft der Atmega? Bei Vorteiler 1 würde eine LED schon irre schnell blinken, so daß man das nicht sehen kann.

Diese Zeile hier "ldi r16, 0x01 ; setze Pin 1 als High." ist irreführend kommentiert. Damit wird Bit 0 in r16 gesetzt. Später in der ISR wird damit PB0 getoggelt (mal abgesehen davon, daß auch alle anderen PBs in der ISR getoggelt werden.)

Beschreib genau was Du wie erwartest und wo (Simulator, in der Schaltung, ...) und was da nicht geht.

Gruß
Searcher

Saturas077
23.04.2014, 08:09
Ich habe gehofft, dass wenn der Interrupt auslöst die Pins an Port B alle einen High-Pegel bekommen bis auf der Pin0. Sobald dann die Hauptschleife anläuft soll wieder nur Pin 0 leuchten.

Das Bild zeigt wie es im Simulator aussieht:
28050
Auf dem Bild siehst du auch die Taktrate von 8Mhz, statt 1 Mhz

Es wird durch das Programm alles gesetzt wie im Zitat am Anfang des Threades beschrieben.
Er springt aber einfach nicht in die Interrupt Routine, deshalb wird auch der Code nicht ausgelöst

E: Was mir noch auffällt, das der Programm Counter bei der Adresse 13 bei main ankommt.
Im Speicher steht : 0x0000 dann kommt direkt 0x0013.

Kurz Offtopic, wieso stehen die Zahlen in 0x0013? Wäre das nicht 0x0D?

Searcher
23.04.2014, 12:32
Ich habe gehofft, dass wenn der Interrupt auslöst die Pins an Port B alle einen High-Pegel bekommen bis auf der Pin0. Sobald dann die Hauptschleife anläuft soll wieder nur Pin 0 leuchten.

Ich denke, daß das Programm zuerst die Hauptschleife erreicht, bevor der erste Interrupt auftritt - der Timer0 muß ja erstmal bis 255 hochlaufen nachdem er mit dem CS00 Bit gestartet wurde. (Könnte in einer Simulation schon einiges dauern)

Tritt dann der erste Interrupt auf, wird PB0 auf high (1) gelegt und r16 invertiert. Beim zweiten Interrupt wird dann PB0 auf low (0) gesetzt. usw.

Im Programmablauf sehe ich keinen Grund, warum der PB0 nicht toggeln sollte (wenn RETI am Ende der ISR steht) und das rjmp Interrupt auch auf dem OVF0 Interruptvektor steht - also die syntax auch vom übrigen Code paßt.


E: Was mir noch auffällt, das der Programm Counter bei der Adresse 13 bei main ankommt.
Im Speicher steht : 0x0000 dann kommt direkt 0x0013.

Kurz Offtopic, wieso stehen die Zahlen in 0x0013? Wäre das nicht 0x0D?

Der Programmcounter umfasst 2 Byte! - Könnte es das sein? Wie gesagt kann ich das leider nicht nachtesten.

Ich vermute eventuell einen Simulator Bug oder Einstellung wie zB:
http://www.mikrocontroller.net/topic/292982

Gruß
Searcher

Saturas077
23.04.2014, 12:46
Danke für deine Bestätigung, das der Code eigentlich funktionieren sollte.
Genau das beschriebene Phänomen aus deinem Link habe ich "manchmal" auch.
Ich habe mein MK II geschrottet, kann mir als Student diesen Monat keinen neuen Leisten, werde es also erst im Mai an einem AVR ausprobieren können.
Danke für deine Hilfe.