PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Interrupt Timer1



Stefan_84
05.12.2015, 14:14
Guten Tag!
Ich hab bei einem Projekt mit einem Atiny 2313 folgendes Problem:

Das Programm sollte eine Zeit von (ca.) 6 Minuten runter zählen. Dafür wollte ich den Timer1 verwenden der bis 7812 zählen sollte und dann einen Interrupt auslösen soll um dann eine Sekunde abzuziehen.

Der Timer1 zählt auch wie geplant hoch, bei 7812 beginnt er von vorne und setzt das OCF1A Bit auf 1 aber dadruch wird kein Interrupt ausgelöst.

Der Timer wurde wie folgt konfiguriert:


;Timer einstellen-------------------------------
;--Vergleichswert
ldi tmp1, 0b00011110
out ocr1ah, tmp1
ldi tmp1, 0b10000100
out ocr1al, tmp1

;--TCCR1a & TCCR1c werden nicht gebraucht
clr tmp1
out tccr1a, tmp1
out tccr1c, tmp1

;--CTC aktivieren und den Teiler auf 1024 stellen
ldi tmp1, 0b00001101
out tccr1b, tmp1

;--Timer1 Output Compare A Match interrupt enabled
ldi tmp1, 0b01000000
out timsk, tmp1

;Interrupt einschalten
sei
;-----------------------------

Kann mir vielleicht jemand sagen was falsch gelaufen ist? Ich hab das Datenblatt jetzt x-mal durchgelesen und ich konnte aber keinen Fehler entdecken.

Danke.
mfg
Stefan

Unregistriert
05.12.2015, 16:39
Sieht alles richtig aus. Zeige den kompletten Code. Interessant ist es, wie du überprüfst, ob ein Interrupt aufgetreten ist. Wie überprüfst du das?

Stefan_84
05.12.2015, 21:53
.include "tn2313def.inc"

;--KONSTANTENDEKLARATION---------------------------------------------
; status register bits
.equ CarryFlag = 0
.equ ZeroFlag = 1
.equ NegativeFlag = 2
.equ TwosFlag = 3
.equ SignFlag = 4
.equ HalfCarryFlag = 5
.equ TransferFlag = 6
.equ GlobalFlag = 7
.equ Frequenz = 8000000
.equ Teiler = 4000

;--VARIABLENDEKLARATION----------------------------------------

.CSEG
.org 0x0000

rjmp MAIN ;Reset
rjmp taster ;Ext. Int0
rjmp UnusedInt_ISR;takt ;Ext. Int1
rjmp UnusedInt_ISR ;Timer1 Capture Event
rjmp takt ;Timer1 Compare Match A
rjmp UnusedInt_ISR ;Timer1 Overflow
rjmp UnusedInt_ISR ;Timer0 Overflow
rjmp UnusedInt_ISR ;USART Rx Complete
rjmp UnusedInt_ISR ;USART Data Reg. Empty
rjmp UnusedInt_ISR ;USART Tx Complete
rjmp UnusedInt_ISR ;Analog Comperator
rjmp UnusedInt_ISR ;Pin Change Int
rjmp UnusedInt_ISR ;Timer1 Compare MatchB
rjmp UnusedInt_ISR ;Timer0 Compare MatchA
rjmp UnusedInt_ISR ;Timer0 Compare MatchB
rjmp UnusedInt_ISR ;USI Start Cond
rjmp UnusedInt_ISR ;USI Overflow
rjmp speichern ;EEPRom Ready
rjmp UnusedInt_ISR ;Watchdog Timer Overflow
UnusedInt_ISR: reti


;Variabelen
.def sreg_save = R16
.def set_zeit = R17
.def set_klasse = R18
.def minu = R19
.def sek = R20
.def tmp1 = R21
.def tmp2 = R22
.def tmp3 = R23
.def pos_klasse = R24

;--Hauptprogramm------------------------------------------------
MAIN:
;Stackpointer initialisieren
ldi tmp1,low (RAMEND) ; RAMEND ist eine im include file vorgegebene Konstante,
out SPL,tmp1
rjmp init

main_loop:
clr tmp1
cpse minu, tmp1
rjmp main_loop
ldi tmp1, 0b00011110 ;30Sek vor Ende
cpse sek, tmp1
rjmp main_loop
summer_ein:
ldi tmp1, 0b010
out porta, tmp1
ldi tmp1, 0b00011001 ;25Sek vor Ende
cpse sek, tmp1
rjmp summer_ein
summer_aus:
ldi tmp1, 0b000
out porta, tmp1
clr tmp1
cpse sek, tmp1
rjmp summer_aus
rcall umschalten
rjmp main_loop


init:
;Setup Beschreibung
;Anzahl der Klassen:
;Dip 1-2
;00 = 2
;01 = 3
;10 = 4
;11 = 5
;Zeit
;Dip 3-5
;000 = 6 Min
;001 = 9 Min
;010 = 12 Min
;011 = 15 Min
;...
;-----------------------------------------------
clr sek
clr minu
;Eingänge setzen--------------------------------
clr tmp1
out ddrb, tmp1
;Ausgänge setzen--------------------------------
ldi tmp1, 0b11110011
out ddrd, tmp1 ; Lampen
ser tmp1
out ddra, tmp1 ; Summer
;Reset------------------------------------------
;--FF--Speicher resten

;Interrupt einstellen--------------------------
ldi tmp1, 0b00001010 ;Bit2&3 Int1 @ Fallende Flanke
out mcucr, tmp1
ldi tmp1, 0b11000000 ;Bit7 Int1 ein;
out gimsk, tmp1
;Timer einstellen-------------------------------
;--Vergleichswert
ldi tmp1, 0b00011110
out ocr1ah, tmp1
ldi tmp1, 0b10000100
out ocr1al, tmp1
;--TCCR1a & TCCR1c werden nicht gebraucht
clr tmp1
out tccr1a, tmp1
out tccr1c, tmp1
;--CTC aktivieren und den Teiler auf 1024 stellen
ldi tmp1, 0b00001101
out tccr1b, tmp1
;--Timer1 Output Compare A Match interrupt enabled
ldi tmp1, 0b01000000
out timsk, tmp1
;Interrupt einschalten
sei
;-----------------------------

;-----------------------------
;Einstellungen einlesen
;Anzahl Klassen
in set_klasse, pinb
andi set_klasse, 0b00000011
inc set_klasse
inc set_klasse
;Zeitintervall
in set_zeit, pinb
andi set_zeit, 0b00011100
lsr set_zeit
lsr set_zeit
clr tmp1
cp set_zeit, tmp1
breq zeitintervall_ende
clr tmp1
add tmp1, set_zeit
clr set_zeit
rep_zeit:
dec tmp1
inc set_zeit
inc set_zeit
inc set_zeit
clr tmp2
cpse tmp1, tmp2
rjmp rep_zeit
zeitintervall_ende:
ldi tmp1, 0b00000110
add set_zeit, tmp1
;Klassenposition------------------------
;--FF--Pos_Speicher lesen und pos_klasse zuteilen
cp set_klasse, pos_klasse
brlo error1
clr tmp1
cp tmp1, pos_klasse
breq error1
;Zeit starten---------------------------
rcall umschalten
rjmp main_loop
error1:
clr pos_klasse
add pos_klasse, set_klasse
;--FF--speichern pos_klasse
rjmp main
;Init Ende---------------------------------------------------
takt:
in sreg_save, sreg
;Sekunden
clr tmp1
cpse sek, tmp1
ldi sek, 0b00110010
dec sek
;Minuten
ldi tmp1, 0b00110001
cpse sek, tmp1
dec minu
out sreg, sreg_save
reti

taster:
in sreg_save, sreg
clr minu
ldi sek, 0b00000011
;--FF-- Entprellen und direkt umschalten
out sreg, sreg_save
reti

speichern:
in sreg_save, sreg
out sreg, sreg_save
reti

umschalten:
clr minu
clr sek
add minu, set_zeit
cp set_klasse, pos_klasse
breq umschalt1
inc pos_klasse
ldi tmp1, 0b00000010
cp tmp1, pos_klasse
breq umschalt2
ldi tmp1, 0b00000011
cp tmp1, pos_klasse
breq umschalt3
ldi tmp1, 0b00000100
cp tmp1, pos_klasse
breq umschalt4
ldi tmp1, 0b00000101
cp tmp1, pos_klasse
breq umschalt5
umschalt1:
ldi pos_klasse, 0b00000001
ldi tmp1, 0b00000001
out portd, tmp1
rjmp umschalt_ende
umschalt2:
ldi tmp1, 0b00000010
out portd, tmp1
rjmp umschalt_ende
umschalt3:
ldi tmp1, 0b00010000
out portd, tmp1
rjmp umschalt_ende
umschalt4:
ldi tmp1, 0b00100000
out portd, tmp1
rjmp umschalt_ende
umschalt5:
ldi tmp1, 0b01000000
out portd, tmp1
umschalt_ende:
;--FF--Position speichern
reti

Naja. Habs nur so im AVR Studio getestet. Hab auf den Timer gewartet und die Register beobachtet (mit F11 durchgedrückt). Der Interrupt wurde nicht ausgeführt.
Der Code ist noch eine Baustelle. Daher wurde er nicht am Controller getestet.

mfg
Stefan

wkrug
06.12.2015, 09:25
Irgendwie fehlt mir da die generelle Interruptfreigabe mit "SEI".
Habs aber vieleicht auch übersehen.

Stefan_84
06.12.2015, 09:27
Kurzes Update:
Hab das Programm auf den Controller geladen und steure jetzt mit dem Interrupt ein Relais an (einmal ein, beim nächsten aus...), zum Testen ob es funktioniert. Erst klappte es nicht.
Hab die Software nochmals überflogen und einen Fehler gefunden. Jetzt klappts. Auch wenn es noch keine Sekunde ist. Da hab ich mich wohl verrechnet.
Aber danke erstmal.

mfg
Stefan

- - - Aktualisiert - - -

Der SEI Befehl kommt direkt nach dem einstellen der Timer.

mfg

Stefan_84
08.12.2015, 09:39
Noch kurz als Ergänzung.

Bin jetzt drauf gekommen warum die Interrupts im AVR Studio nicht ausgeführt werden. "Mask interrupt while stepping" muss in den Optionen auf "False" gesetzt werden. Dann klappt es auch beim simulieren.

mfg
Stefan