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.