Hallo Forengemeinde,
benötige bei der Timerprogrammierung einen Denkanstoss.
Habe testweise einmal die folgende Programme erstellt.
Programm 1:
--------------------------------------------------
.include "m88def.inc"
.equ fq = 16000000 ; Quarzfrequenz
.equ baud = 19200 ; Baudrate RS-232 Schnittstelle
.equ bddivH = 0x00 ; Teilfaktor für Baudrate Highbyte
.equ bddivL = (fq/(16*baud))-1 ; Teilfaktor für Baudrate Lowbyte
.def temp = r16
.def leds = r17
.def temp2= r18
.org 0x0000
rjmp main ; Reset Handler
reti ; IRQ0 Handler
reti ; IRQ1 Handler
reti ; PCINT0 Handler
reti ; PCINT1 Handler
reti ; PCINT2 Handler
reti ; Watchdog Timer Handler
reti ; Timer2 Compare A Handler
reti ; Timer2 Compare B Handler
reti ; Timer2 Overflow Handler
reti ; Timer1 Capture Handler
reti ; Timer1 Compare A Handler
reti ; Timer1 Compare B Handler
reti ; Timer1 Overflow Handler
reti ; Timer0 Compare A Handler
reti ; Timer0 Compare B Handler
reti ; Timer0 Overflow Handler
reti ; SPI Transfer Complete Handler
reti ; USART, RX Complete Handler
reti ; USART, UDR Empty Handler
reti ; USART, TX Complete Handler
reti ; Analog Comparator Handler
reti ; 2-wire Serial Interface Handler
reti ; Store Programm Memory Ready Handler
main:
; Initialisieren
ldi temp, high(RAMEND) ; Stackpointer H initialisieren
out SPH, temp
ldi temp, low(RAMEND) ; Stackpointer L initialisieren
out SPL, temp
ldi temp, 0b00000111 ; Port C0,C1 und C2 Ausgang, Rest
Eingänge
out DDRC, temp ; in Register schreiben
ldi leds, 0xFF ; alle Ausgänge auf high
; Timer0 initialisieren
ldi temp, (1<<CS01|0<<CS00) ; CS1 setzen: Teiler 8
out TCCR0B, temp ; in Register speichern
ldi temp, (1<<TOIE0) ; TOIE0: Interrupt bei Timer Overflow
sts TIMSK0, temp ; in Register speichern
sei ; Interupts aktivieren
loop: out PORTC,leds
wait: in temp, TIFR0
sbrs temp, $0
rjmp wait
ldi temp, 0x01
out TIFR0, temp
com leds
out PORTC,leds
wait1: in temp, TIFR0
sbrs temp, $0
rjmp wait1
ldi temp, 0x01
out TIFR0, temp
rjmp loop ; Schleife
------------------------------------------------
Dieses Programm erzeugt mir einen Rechteckimpuls mit einer Periodendauer
von 1792 µs.
-------------------------------------------------
.include "m88def.inc"
.equ fq = 16000000 ; Quarzfrequenz
.equ baud = 19200 ; Baudrate RS-232 Schnittstelle
.equ bddivH = 0x00 ; Teilfaktor für Baudrate Highbyte
.equ bddivL = (fq/(16*baud))-1 ; Teilfaktor für Baudrate Lowbyte
.def temp = r16
.def leds = r17
.def temp2= r18
.org 0x0000
rjmp main ; Reset Handler
reti ; IRQ0 Handler
reti ; IRQ1 Handler
reti ; PCINT0 Handler
reti ; PCINT1 Handler
reti ; PCINT2 Handler
reti ; Watchdog Timer Handler
reti ; Timer2 Compare A Handler
reti ; Timer2 Compare B Handler
reti ; Timer2 Overflow Handler
reti ; Timer1 Capture Handler
reti ; Timer1 Compare A Handler
reti ; Timer1 Compare B Handler
reti ; Timer1 Overflow Handler
reti ; Timer0 Compare A Handler
reti ; Timer0 Compare B Handler
reti ; Timer0 Overflow Handler
reti ; SPI Transfer Complete Handler
reti ; USART, RX Complete Handler
reti ; USART, UDR Empty Handler
reti ; USART, TX Complete Handler
reti ; Analog Comparator Handler
reti ; 2-wire Serial Interface Handler
reti ; Store Programm Memory Ready Handler
main:
; Initialisieren
ldi temp, high(RAMEND) ; Stackpointer H initialisieren
out SPH, temp
ldi temp, low(RAMEND) ; Stackpointer L initialisieren
out SPL, temp
ldi temp, 0b00000111 ; Port C0,C1 und C2 Ausgang, Rest
Eingänge
out DDRC, temp ; in Register schreiben
ldi leds, 0xFF ; alle Ausgänge auf high
; Timer0 initialisieren
ldi temp, (1<<CS01|0<<CS00) ; CS1 setzen: Teiler 8
out TCCR0B, temp ; in Register speichern
ldi temp, (1<<OCIE0A) ; OCIE0A: Interrupt bei Timer CompareA
Overflow
sts TIMSK0, temp ; in Register speichern
ldi temp, $77
sts OCR0A, temp
sei ; Interupts aktivieren
loop:out PORTC,leds
wait:in temp, TIFR0
sbrs temp, $02
rjmp wait
sbi TIFR0, (1<<OCF0A)
com leds
out PORTC,leds
wait1:in temp, TIFR0
sbrs temp, $02
rjmp wait1
sbi TIFR0, (1<<OCF0A)
rjmp loop ; Schleife
------------------------------------------------
Dieses Programm erzeugt mir einen Rechteckimpuls mit einer Periodendauer
von 512 µs.
Ich benötige aber eine Periodendauer ca. 366 µs.
Dazu lädt man doch normalerweise den benötigten Wert in das
CompareA-Register und fragt ab ob das CompareA Register mit dem TCNTo
identisch ist.
Was mache ich falsch oder wo liegt mein Gedankenfehler?
Ich möchte es nicht über eine Interuptroutine lösen. Das habe ich
getestet
und dies funktioniert auch.
Gruß
NobbyH
Hi >Dazu lädt man doch normalerweise den benötigten Wert in das >CompareA-Register und fragt ab ob das CompareA Register mit dem TCNTo >identisch ist. Nein. Man benutzt den CTC-Mode. Dann macht der Timer alles allein. MfG Spess
Der Interruptcontroller löscht beim Auftreten des Interrupts das Interruptflag TIFR0 und springt deine Interruptroutine an. Die besteht zwar nur aus einem RETI, aber nichts desto trotz ist das Flag gelöscht. Dein Hauptprogramm hat schlechte Karten, wenn es TIFR0 selbst abfragt. Versuche eigene ISRs zu implementieren und setze dort ein eigenes Flag, welches du im Hauptprogramm abfragen und löschen (quittieren) kannst.
> Der Interruptcontroller löscht beim Auftreten des Interrupts das > Interruptflag TIFR0 und springt deine Interruptroutine an. Das ist der Effekt des SEI; teste dein Programm mal ohne das SEI. Beachte, dass du dann das Interruptflag TIFR0 selbst löschen musst (durch Beschreiben mit einem 1 an der Stelle des Bitflags).
Danke an Alle für die vielen Tips.
Werde sie alle testen.
Habe mal den Vorschlag von Spess versucht zu realisieren.
Das hat soweit bei Timer1 und Timer2 funktioniert.
Leider funktioniert die gleiche Rountine (angepaßt) bei Timer0 nicht.
Mir ist nicht klar warum.
Hier die Programmsequenz für Timer2:
;--------------------------------------------------------------
.include "m88def.inc"
.def temp1 = r16
.def temp2 = r17
.def temp3 = r18
.def Flag = r19
.def temp = r20
.def leds = r21
.org 0x0000
rjmp main ; Reset Handler
reti ; IRQ0 Handler
reti ; IRQ1 Handler
reti ; PCINT0 Handler
reti ; PCINT1 Handler
reti ; PCINT2 Handler
reti ; Watchdog Timer Handler
rjmp timer2_compare ; Timer2 Compare A Handler
reti ; Timer2 Compare B Handler
reti ; Timer2 Overflow Handler
reti ; Timer1 Capture Handler
reti ; Timer1 Compare A Handler
reti ; Timer1 Compare B Handler
reti ; Timer1 Overflow Handler
reti ; Timer0 Compare A Handler
reti ; Timer0 Compare B Handler
reti ; Timer0 Overflow Handler
reti ; SPI Transfer Complete Handler
reti ; USART, RX Complete Handler
reti ; USART, UDR Empty Handler
reti ; USART, TX Complete Handler
reti ; Analog Comparator Handler
reti ; 2-wire Serial Interface Handler
reti ; Store Programm Memory Ready Handler
main:
ldi temp1, HIGH(RAMEND)
out SPH, temp1
ldi temp1, LOW(RAMEND) ; Stackpointer initialisieren
out SPL, temp1
; IO initialisieren
ldi temp, 0b00000111 ; Port C0,C1 und C2 Ausgang, Rest
Eingänge
out DDRC, temp ; in Register schreiben
ldi leds, 0xFF ; alle Ausgänge auf high
; Vergleichswert
ldi temp1, ( 183 - 1 )
sts OCR2A, temp1 ; CTC Modus einschalten
ldi temp1, ( 1 << WGM21 )
sts TCCR2A, temp1
; Vorteiler auf 32
ldi temp1, ( 1 << CS21 | 1<<CS20)
sts TCCR2B, temp1
ldi temp1, (1 << OCIE2A); OCIE2A: Interrupt bei Timer
Compare
sts TIMSK2, temp1
clr Flag ; Flag löschen
sei
loop:
cpi flag,0
breq loop ; Flag im Interrupt gesetzt?
com leds
out PORTC,leds
ldi flag,0 ; Flag löschen
rjmp loop
timer2_compare: ; Timer 2 Output Compare Handler
ldi flag,1 ; Flag setzen, LCD updaten
reti ; das wars. Interrupt ist fertig
;--------------------------------------------------------------
Hier die Programmsequenz für Timer0:
.include "m88def.inc"
.def temp1 = r16
.def temp2 = r17
.def temp3 = r18
.def Flag = r19
.def temp = r20
.def leds = r21
.org 0x0000
rjmp main ; Reset Handler
.org OC0Aaddr
rjmp timer0_compare ; Timer Compare Handler
;.org 0x0000
; rjmp main ; Reset Handler
; reti ; IRQ0 Handler
; reti ; IRQ1 Handler
; reti ; PCINT0 Handler
; reti ; PCINT1 Handler
; reti ; PCINT2 Handler
; reti ; Watchdog Timer Handler
; reti ; Timer2 Compare A Handler
; reti ; Timer2 Compare B Handler
; reti ; Timer2 Overflow Handler
; reti ; Timer1 Capture Handler
; reti ; Timer1 Compare A Handler
; reti ; Timer1 Compare B Handler
; reti ; Timer1 Overflow Handler
; rjmp timer0_compare ; Timer0 Compare A Handler
; reti ; Timer0 Compare B Handler
; reti ; Timer0 Overflow Handler
; reti ; SPI Transfer Complete Handler
; reti ; USART, RX Complete Handler
; reti ; USART, UDR Empty Handler
; reti ; USART, TX Complete Handler
; reti ; ADC Conversion Complete Handler
; reti ; EEPROM Ready Handler
; reti ; Analog Comparator Handler
; reti ; 2-wire Serial Interface Handler
; reti ; Store Programm Memory Ready Handler
main:
ldi temp1, HIGH(RAMEND)
out SPH, temp1
ldi temp1, LOW(RAMEND) ; Stackpointer initialisieren
out SPL, temp1
; IO initialisieren
ldi temp, 0b00000111 ; Port C0,C1 und C2 Ausgang, Rest
Eingänge
out DDRC, temp ; in Register schreiben
ldi leds, 0xFF ; alle Ausgänge auf high
; Vergleichswert
ldi temp1, ( 181 - 1 )
out OCR0A, temp1
; CTC Modus einschalten
ldi temp1, ( 1 << WGM01 )
sts TCCR0A, temp1
; Vorteiler auf 8
ldi temp1, ( 1 << CS01 | 0<<CS00)
sts TCCR0B, temp1
ldi temp1, (1 << OCIE0A); OCIE0A: Interrupt bei Timer
Compare
sts TIMSK0, temp1
clr Flag ; Flag löschen
sei
loop:
cpi flag,0
breq loop ; Flag im Interrupt gesetzt?
com leds
out PORTC,leds
ldi flag,0 ; Flag löschen
rjmp loop
timer0_compare: ; Timer 0 Output Compare Handler
push temp1 ; temp 1 sichern
in temp1,sreg ; SREG sichern
ldi flag,1 ; Flag setzen, LCD updaten
out sreg,temp1 ; sreg wieder herstellen
pop temp1
reti ; das wars. Interrupt ist fertig
-------------------------------------------------
Hat jemand eine Tip für mich? Gibt es Unterschiede zwischen Timero und
Timer1 die ich nicht beachtet habe?
Danke und Gruß
NobbyH
NobbyH schrieb: > Hat jemand eine Tip für mich? Gibt es Unterschiede zwischen Timero und > Timer1 die ich nicht beachtet habe? Timer1 existiert im ATmega88, Timero nicht.
Hi > ldi temp1, ( 1 << CS01 | 0<<CS00) > sts TCCR0B, temp1 !!!!!!!!!!!!!!!!!!!!!!!!! Die Register TCCR0A, TCCR0B, OCR0A, OCR0B, GTCCR, aber nicht TIMSK0, des ATMega88 werden mit out/in angesprochen. MfG Spess
@Spess, Vielen Dank für die sachkundige kompetente Antwort. Das war der Fehler. Manchmal hat man halt ein Brett vorm Kopf. Gruß und schöne Ostertage wünscht NobbyH
NobbyH schrieb: > Manchmal hat man halt ein Brett vorm Kopf. Durch welches man schlecht auf das Datenblatt ded mega88 gucken kann.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.