TIMER0 "fast PWM" Frage zu höherer Frequenz bei geringerer Auflösung

OP #7879060
Lesenswert?

Hallo,

wie kann ich eine möglichst hohe PWM-Frequenz erzeugen, wenn ich dafür die Auflösung opfere?

Der ATtiny13 (Target) schafft mit seinem internen Oszillator 9,6MHz. Daraus ergibt sich bei 256bit Auflösung eine PWM-Frequenz von 37,5kHz.

Angenommen, es reicht eine Auflösung von z.B. 128Bit. Damit käme man auf 75kHz. Nur wie realisiere so ich ein PWM-Signal?

Wie muß ich die Register bedaten? Was ist per SW zu tun, z.B. in der Interrupt-Routine?

TCCR0A = ??? (1 << COM0A0) | (1 << WGM01); // CTC Modus 2, bei CompMatch wird TCNT0 resettiert und OC0A-Pin getoggelt; TIMSK0 = (1 << OCIE0B); // Interrupt enable für OCR0B CompMatch OCR0A = 128; // Periodendauer des PWM-Signals OCR0B = duty; // Dauer der Hi-Phase des PWM-Signals

//TIMER0 starten TCCR0B = TCCR0B = (1 << CS00); // CS00 bit für prescaler=1 OC0A-Pin = 1; // PWM starten

ISR(TIMER0_COMPB_vect) { OC0A-Pin = 0; // PWM-Pin invertieren }

Würde das grundsätzlich funktionieren, oder gibt es eine bessere Methode, PWM mit unterschiedlichen Auflösungen und Frequenzen zu erzeugen?

#7879076
Lesenswert?

StefanK schrieb:

256bit

Ne, nur 8bit, respektive 7bit.

StefanK schrieb:

ISR(TIMER0_COMPB_vect) { OC0A-Pin = 0; // PWM-Pin invertieren }

Ne, das Invertieren musst du per Register einstellen.

StefanK schrieb:

Wie muß ich die Register bedaten?

Es gibt einen Modus, wo TCCR das Maximum definiert und OCR0x bei compare match nicht toggeln, sondern den jeweiligen Pin Setzen bzw. Rücksetzen. Rücksetzen bzw. Setzen kommt automatisch beim Umsprung des Timers auf 0. Steht alles im Datenblatt.

StefanK schrieb:

Was ist per SW zu tun, z.B. in der Interrupt-Routine?

Na deinen neuen OCR0x schreiben. Beim Umsprung des Timers auf 0 wird der in ein Schattenregister geladen, womit zwar deine OCR0x erst in der nächsten Periode verwendet werden, dafür hast du eine Race-Condition per Hardware aufgelöst.

mfg mf

(Firma: 1984now) #7879078
Lesenswert?

StefanK schrieb:

Angenommen, es reicht eine Auflösung von z.B. 128Bit. Damit käme man auf 75kHz. Nur wie realisiere so ich ein PWM-Signal?

Niemals nicht. Du meinst entweder eine Auflösung von 128 diskreten Zuständen oder (gleichbedeutend) eine von 7 Bit. Damit wären dann die ca. 75kHz erreichbar. "128 Bit" ist einfach Unfug.

Wie muß ich die Register bedaten? Was ist per SW zu tun, z.B. in der Interrupt-Routine?

Kann man machen. Aber gerade bei der Registeraktualisierung gibt es Fallstricke zu beachten. Nicht in jedem Timer-Modus ist eine sichere Aktualisierung durch gepufferte Register verfügbar. Das gilt insbesondere für die Änderung der Frequenz. Duty hingegen ist typisch in allen PWM-Modi gepuffert.

OCR0A = 128; // Periodendauer des

Das sollte übrigens lauten: "OCR0A = 127", wenn 7 bit bzw. 128 Stufen angestrebt werden.

Würde das grundsätzlich funktionieren

Natürlich.

oder gibt es eine bessere Methode, PWM mit unterschiedlichen Auflösungen und Frequenzen zu erzeugen?

Nur für die Timer1/3 der klassischen AtMega oder für die D-Type-Timer der neueren Baureihen. Da sind auch gepufferte Frequenzänderungen möglich.

OP #7879083
Lesenswert?

Modus 7 also, OK danke. Das mit den 256bit sollte natürlich 256 Inkremente heissen, klar.

Das PWM-Signal soll für die Dauer von OCR0B hi sein und bei Compare Match mit OCR0B auf lo gehen. Bei Compare Match von OCR0A soll der PWM-Pin wieder auf hi gehen, der TCNT0=0 und eine neue Periode gestartet werden.

Wie muß ich TCCR0B und TCCR0B für Modus 7 bedaten?

(Firma: 1984now) #7879096
Lesenswert?

Achim M. schrieb:

Oops! Danke für die Klarstellung. Das würde bedeuten, dass man vor OCR0x beschreiben den Timer anhalten muss, gucken ob er schon da war und den neuen Wert oder eben direkt den Ausgang beschreiben muss. Danach den Timer wieder starten... Puuuh...

Nö. Das wäre ja bezüglich der Auswirkungen noch schlimmer als als der Fehler durch ungepufferte Periodenregister. Praktisch wohl fast unbrauchbar.

#7879099
Lesenswert?

an StefanK: Dies ist für einen ATtiny85 (und in Assembler) - auf Ihre Verhältnisse umsetzen müssen Sie selbst, aber das Prinzip sollte klar werden.

1
    sbi     DDRB,1                                  ; OC0B: PWM-Pin auf Ausgang
2
    puti    OCR0A,128 -1                            ; TOP
3
    puti    OCR0B,76                                ; duty
4
    puti    TCCR0A,(1<<COM0B1)|(1<<WGM01)|(1<<WGM00); PWM, Modus 7
5
    puti    TCCR0B,(1<<WGM02)|(1<<CS00)             ; /1
6

7
main_loop:
8
  rjmp      main_loop
(Firma: 1984now) #7879156
Lesenswert?

Rick schrieb:

Falls es mal eine Schippe mehr sein darf, die Tiny 25/45/85 haben eine PLL, die 64 MHz erzeugt (PCK) um Timer1 zu takten. Damit sind 500 kHz PWM-Frequenz (bei 7 Bit) machbar. Mit 8 Bit Auflösung reicht es noch für 250 kHz...

Ja, das habe ich z.B. hier

Beitrag "Westminster Soundgenerator mit ATtiny85"

benutzt.

Aber: An der PWM-Frequenz würde ich da nicht zur Laufzeit herumfummeln wollen...

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