Hallo, angenommen mein uC hat eine Fcpu von 8Mhz. ich will am PWM Ausgang eine Frequenz von 1khz erzeugen. (50% Tastgrad, Atmega32, Timer0) wie gehe ich hier vor? Meine Überlegung war... Prescaler von 64... ergibt einen wert von 125... Ich lade meine TCNT0 mit 131 vor. (256-125) und setze meinen OCR0 auf 193 (125/2+131) da wenn ich einen Prescaler von 64 Nehme der ca. 490Hz macht und keine 1Khz. und das heißt dass ich erst bei 131 starten muss und der somit nur die 125 takte geht.... Richtig? oder denke ich da falsch?
Hallo, wenn es immer 50% sind, ist keine PWM und damit bietet sich der CTC-Mode des Timers an, den muß man dann nur initialisieren und den Rest macht er alleine. Gruß aus Berlin Michael
Ich denke, den TCNT0 vorzuladen ist keine gute Idee. Denn dadurch reduzierst du die Auflösung des PWM Signals. Kannst du die Taktfrequenz nicht passend ändern, dass es ohne diesen trick klappt? Muss das PWM Signal wirklich 1kHz haben?
es muss nicht... es war einfach nur eine Verständnisfrage bzgl. des TCNT0
leo schrieb: > angenommen mein uC hat eine Fcpu von 8Mhz. > ich will am PWM Ausgang eine Frequenz von 1khz erzeugen. (50% Tastgrad, > Atmega32, Timer0) > > wie gehe ich hier vor? Man überlegt sich, ob die 50% duty tatsächlich konstant sein sollen. Falls ja, dann benutzt man den CTC-Modus. Falls nein (das wäre der Normalfall für PWM), überlegt man, wie genau die 1kHz Zyklusfrequenz tatsächlich erreicht werden müssen und ob das dann mit den geringen Möglichkeiten des Timer0 dieses uralt-AVR machbar wäre. (sieht schlecht aus: entweder ca. 2kHz mit Prescaler 8 und phase correct PWM oder ca. 500Hz mit Prescaler 64 und fast PWM). Wenn das nicht akzeptabel ist, nimmt man einen anderen Timer oder einen moderneren pinkompatiblen AVR mit mehr Freiheitsgraden in Timer0. So einfach ist das eigentlich...
Also wenn es um das Verständnis geht, dann berücksichtige auch, dass du nie genau weisst, wann die Interruptroutine aufgerufen wird. Wenn der Timer gerade von 0xFF nach 0x00 überläuft, wird deine Interruputroutine danach möglichwerweise so weit verzögert ausgeführt, dass der Timer schon weiter gezählt hat. Wenn der Timer dann zum Beispiel schon bei 0x01 angekommen ist, erhälst du keine konstante Frequenz mehr und keine Konstante Pulsbreite. Es sei denn, du rechnest das raus, was aber auch wieder Rechenzeit kostet. Bei hoher Timer-Taktfrequenz geht das gar nicht sinnvoll. Mit Prescaler 64 kann ich mir allerdings vorstellen, das noch hin zu bekommen - wenn es denn unbedingt sein muss.
ok:) danke.. aber habe das eben mal aufgebaut und getestet. Ich kann den TCNT0 mit 131 vorladen... und dann OCR0 auf 192 setzen... ABER: ich muss in meiner while schleife abfragen If(TCNT0 == 0) { TCNT0 = 131} :) und somit reicht es mir für meine verständis.. ich weiß... es kann sein das meine If abfrage evtl. gar nicht TRUE wird... je nachdem wo der Timer grade überläuft... aber wie gesagt... war nur ne Frage... kein praktischer Fall
Hallo, da wird nichts vorgeladen. Man stellt mit einem Register den gewünschten Takt ein im Zusammenhang mit dem Prescaler. Und im anderen Register den Vergleichswert für das Tastverhältnis. Aber. Timer 0 zu verwenden mit Arduino ist keine gute Idee. Damit verstellst du alle Komfortfunktionen wie millis, analogWrite usw. Timer 0 läßt man am besten in Ruhe. Es gibt ja noch mehr Timer. Ich gebe dir mal ein Bsp. mit Timer 1. Register OCR1B kannste live im Programm ändern und damit das Tastverhältnis. Darf nur nie größer werden als OCR1A. Sonst läuft der Timer amok. OCR1A = OCR1B wären 100% Tastverhältnis. Formeln zur Frequenzberechnung, Timereinstellung usw. stehen im Atmel Datenblatt.
1 | const byte Timer1_OC1B = 12; // Pin 12 / OC1B / PB6 ==>> Taktausgang |
2 | |
3 | void setup() { |
4 | |
5 | pinMode(Timer1_OC1B, OUTPUT); // OC1B bzw. PB6 |
6 | |
7 | set_Timer1(); |
8 | }
|
9 | |
10 | |
11 | void loop() { |
12 | |
13 | } // loop Ende |
14 | |
15 | |
16 | // ****** Funktionen ******* //
|
17 | |
18 | void set_Timer1() // Fast-PWM, Mode 15 |
19 | {
|
20 | cli(); // Interrupts ausschalten |
21 | TCCR1A = 0; // Reset TCCR1A Register |
22 | TCCR1B = 0; // Reset TCCR1B Register |
23 | TIMSK1 = 0; // Reset TIMSK1 Register (disable Timer Compare Interrupts) |
24 | TCNT1 = 0; // Start 0 |
25 | OCR1A = 1999; // TOP Wert bestimmt Auflösung und mit Prescaler den PWM Takt, 1kHz |
26 | OCR1B = 499; // Pulsweite, OCR1B <= OCR1A |
27 | TCCR1A = (1<<COM1B1) | (1<<WGM11) | (1<<WGM10); // nicht invertiert |
28 | TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11); // Prescaler 8 |
29 | sei(); // Interrupts einschalten |
30 | } // end Funktion |
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.