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?
Modus 7; ISR ist unnötig bzw. sinnlos.
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
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.
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?
Ob S. schrieb: > Da sind auch gepufferte Frequenzänderungen möglich. 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... mfg mf
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.
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 |
jetzt ist vieles klarewr. Danke an alle!
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...
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...
Georg M. schrieb: > Bei den aktuellen AVR-Mikrocontrollern muss kein PWM-Kanal für die > Periode geopfert werden. Es ging nicht darum, möglichst viel PWM-Käle zu haben, sondern darum, einen möglichst schnellen zu haben. Falls dir das nicht aufgefallen ist...
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.