Forum: Mikrocontroller und Digitale Elektronik verständnisfrage zu PWM


von leo (Gast)


Lesenswert?

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?

von Michael U. (amiga)


Lesenswert?

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

von leo (Gast)


Lesenswert?

dann nehmen wir halt 80%.... ;)
ich will es mit fast PWM mode machen...

von Stefan F. (Gast)


Lesenswert?

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?

von leo (Gast)


Lesenswert?

es muss nicht... es war einfach nur eine Verständnisfrage bzgl. des 
TCNT0

von c-hater (Gast)


Lesenswert?

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...

von Stefan F. (Gast)


Lesenswert?

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.

von leo (Gast)


Lesenswert?

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

von Veit D. (devil-elec)


Lesenswert?

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
Noch kein Account? Hier anmelden.