Da hast du Recht. Ich mache das nachher ganz in Ruhe und gehe die ganzen Flags noch mal durch.
Grüße
Helmut
Da hast du Recht. Ich mache das nachher ganz in Ruhe und gehe die ganzen Flags noch mal durch.
Grüße
Helmut
Hallo Helmut,
ich glaub viel fehlt nicht mehr wenn das TIMSK richtig gesetzt ist. Was passiert im Mode 4, also CTC mit OCR1A als TOP?:
Der Timer läuft nur bis 15625 da OCR1A mit 15625 gesetzt ist. Interrupt Flag wird gesetzt wg. Compare1a Interrupt. Interrupt Compare1A wird ausgeführt und LEDs werden in der ISR eingeschaltet. Der Timer läuft nicht weiter hoch sondern setzt sich auf 0 (Null) wegen CTC. Er erreicht also die 31250 für Compare1B Match gar nicht da TCNT1 vorher zurück gesetzt wird. Compare1B Interrupt kann also nicht eintreten und die LED nie ausgeschaltet werden.Code:;; Output Compare Register 1 A for CTC ; write value 15625 -> 15625 * 1024 = 16MHz -> 1 second count LDI temp, 0b00111101 OUT OCR1AH, temp LDI temp, 0b00001001 OUT OCR1AL, temp ;; Output Compare Register 1 B for CTC ; write value 31,250 -> 31,250 * 1024 = 32MHz -> 2 seconds count LDI temp, 0b01111010 OUT OCR1BH, temp LDI temp, 0b00010010 OUT OCR1BL, temp . . . . . ;------------------------------------------------------------------------------------------- ; interrupts interrupt_compare_A: ; interrupt routine for compare register 1 B IN temp_1, SREG ; save status register LDI temp, 0x00 OUT PORTC, temp ; LEDs on OUT SREG, temp_1 ; restore status register reti interrupt_compare_B: ; interrupt routine for compare register 1 A IN temp_1, SREG ; save status register LDI temp, 0xFF OUT PORTC, temp ; LEDs off OUT SREG, temp_1 ; restore status register reti ;-----------------------------------------------------------------------------------
Also einfach die 15625 ins OCR1B schreiben und die 31250 in OCR1A. Damit läuft der Timer zwei Sekunden hoch. "Oben" schaltet er über den Compare1A Interrupt die LEDs ein und auf dem Weg nach oben über den Compare1B Interrupt die LEDs aus.
Übrigens um genau zwei Sekunden zu erreichen sollte der Wert 31249 statt 31250, da der Timer noch einen Timertick braucht um auf Null zu kommen. Spiegelt sich auch im Datenblatt in der Formel zur Frequenzberechnung mit der -1 wieder. Eventuell auch die 15625 um eins vermindern?
So bin gespannt was sich tut.
Gruß
Searcher
Geändert von Searcher (21.03.2019 um 19:30 Uhr)
Hoffentlich liegt das Ziel auch am Weg
..................................................................Der Weg zu einigen meiner Konstruktionen
Vielen Dank Search, es bliiiiinkt!
Ohne dich hätte ich das glaube ich nicht hinbekommen. Ich hoffe ich brauche das dann auch in meinen Projekten.
Zum einen lag es an den TIMSK Flags, die waren um eine Bitstelle verschoben.
Zum anderen an der zuvor von dir erwähnten Reihenfolge der Faktoren, spricht den Werten in den Vergleichsregistern (OCR1A und OCR1B).
Also einfach die 15625 ins OCR1B schreiben und die 31250 in OCR1A. Damit läuft der Timer zwei Sekunden hoch. "Oben" schaltet er über den Compare1A Interrupt die LEDs ein und auf dem Weg nach oben über den Compare1B Interrupt die LEDs aus.
Die ausgerechnete Zeit muss nicht ganz genau sein. Ich wollte einfach nur im ca. 1 Sekundentakt blinkende LEDs haben.Übrigens um genau zwei Sekunden zu erreichen sollte der Wert 31249 statt 31250, da der Timer noch einen Timertick braucht um auf Null zu kommen. Spiegelt sich auch im Datenblatt in der Formel zur Frequenzberechnung mit der -1 wieder. Eventuell auch die 15625 um eins vermindern?
Falls also jemand mal einen funktionierenden Code braucht mit blinkenden LEDs (ca. 1s), hier ist er.
Code:; Programm : This programm is written and tested on an Atmega32. It causes the LEDs on PORTC to blink on a frequency of 1 second. ; To do so it uses the timer 1 (16-Bit) on CTC mode with a prescaler of 1024. To reach the frequency of 1 second ; the compare register B has the value 15625 and register A the value 31250. The demension of these values result in ; the system clock of 16MHz. ; 1024 * 15625 = 16000000 ; 1024 * 31250 = 32000000 ; definitions .def temp = R16 .def temp_1 = R17 ; interrupt vectors .org 0x000 ; reset handler rjmp main .org 0x00E ; Timer1 CompareA Handler rjmp interrupt_compare_A .org 0x010 ; Timer1 CompareB Handler rjmp interrupt_compare_B ;Mnemonic target, source main: ; main programm ;;; PORTC set as output LDI temp, 0xFF OUT DDRC, temp ; DDRC defines if PORTC is an output (1) or input (0) ;;; Timer Counter in CTC Mode -> self defined value; if timer reaches value, interrupt accours ;; Control Register A LDI temp, 0x00 ; normal & Clear Timer on Compare Match (CTC) Mode OUT TCCR1A, temp ; Control Register A ;; Control Register B LDI temp, 0b00001101 ; Timer prescaler of 1024 & Clear Timer on Compare Match (CTC) Mode -> self adjust overflow value OUT TCCR1B, temp ; Control Register B ;; Output Compare Register 1 A for CTC ; write value 31250 -> 31250 * 1024 = 32MHz -> 2 seconds count LDI temp, 0b01111010 OUT OCR1AH, temp ; first write high register then low LDI temp, 0b00010010 OUT OCR1AL, temp ;; Output Compare Register 1 B for CTC ; write value 15625 -> 15625 * 1024 = 16MHz -> 1 second count LDI temp, 0b00111101 OUT OCR1BH, temp ; first write high register then low LDI temp, 0b00001001 OUT OCR1BL, temp ;;; Interrupt handling ;; for timer 1 Interrupt Mask Register LDI temp, 0b000011000 ; OCIE1A and OCIE1B -> Output Compare A and B Match Interrupt Enable OUT TIMSK, temp ;; global interrupt enable sei loop: rjmp loop ; endless loop ;------------------------------------------------------------------------------------------- ; interrupts ;------------------------------------------------------------------------------------------- interrupt_compare_A: ; interrupt routine for compare register 1 B IN temp_1, SREG ; save status register LDI temp, 0x00 OUT PORTC, temp ; LEDs on OUT SREG, temp_1 ; restore status register reti ; finishes interrupt and enables global interrupt interrupt_compare_B: ; interrupt routine for compare register 1 A IN temp_1, SREG ; save status register LDI temp, 0xFF OUT PORTC, temp ; LEDs off OUT SREG, temp_1 ; restore status register reti ; finishes interrupt and enables global interrupt ;------------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------------
Das ist nicht ganz richtig, ich habe beim Support nachgewühlt, weil wir einen Glitch hatten und das Ergebnis war dass der Timer nicht einen "Timertick" sondern einen "Clocktick" braucht, also nur einen Prozessortakt, hat man also einen großen ClockDivider, wirkt sich der extra takt kaum aus, aber je kleiner der Divider desto stärker der Einfluss des zusätzlichen TaktÜbrigens um genau zwei Sekunden zu erreichen sollte der Wert 31249 statt 31250, da der Timer noch einen Timertick braucht um auf Null zu kommen. Spiegelt sich auch im Datenblatt in der Formel zur Frequenzberechnung mit der -1 wieder. Eventuell auch die 15625 um eins vermindern?
Timer/Counter1 is reset to $00 in the CPU clock cycle after a compare
match with OCR1A register
Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
nicht.
Aber ist nicht ein Timertick gleich einen Clocktick? Also Zählt der timer nicht durch den Clock?
Gruß
Helmut
Das Verhältnis Timerticks zu Clockticks wird durch den entsprechenden Prescaler bestimmt.Aber ist nicht ein Timertick gleich einen Clocktick? Also Zählt der timer nicht durch den Clock? ..
Siehe auch Figure 40. 16-bit Timer/Counter Block Diagram a.a.O.Zitat von ATmega16/16L, 2466T–AVR–07/10, Seite 90
Ciao sagt der JoeamBerg
Was ich nicht verstehe, warum der Timer Takt dadurch verzögert wird ... eigentlich sollte doch bei einem PreScale > 1 die Nullung des Registers fertig sein, bevor der Timer inkrementiert wird, aber scheinbr glitcht auch der prescaler dabei um einen Takt mit, aber das scheint wohl ein Atmel Problem zu sein
Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
nicht.
Hoffentlich liegt das Ziel auch am Weg
..................................................................Der Weg zu einigen meiner Konstruktionen
Lesezeichen