verständnisfrage zu PWM

Gast #4585016
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?
Gast #4585034
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?
Gast #4585068
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...
Gast #4585070
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.
Gast #4585084
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
#4585232
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren