Auch ein Codeschnipsel mit ein paar Kommentaren wäre hilfreich!!!
Gibst doch nicht dass sich hier noch noch nie wer mit dem fast-PWM Mode befasst hat...
Bitte bitte Helft mir...
danke lightwaver
Hallo ...
Ich habe mich soeben urch das lange Kapitel del 16-Bit Timers des Atmel AVR Mega16 gequält, werd aber trotzdem nicht ganz aus dem fast-PWM Mode schlau. Im Endeffekt hätt ich gern ein Ausgamgssignal mit einer High-Time von 25 us und einer Periode von 75 us...
mein Microcontroller läuft auf 16 Mhz...
Nachdem ich leider aus dem Manual nicht ganz schlau werde, wärs cool wenn mir wer erklären könnte was da in welchen Registern stehen soll damit er das Signal erzeugt - bzw. nur die genaue Funktionsweise des fast-PWM Modes erklärt ( wo fängt er zu zählen an - wo schaltet er - wo setzt er den Timer zurück bzw geht wieder auf Low).... den rest sollt ich dann schon schaffen...
Danke im Vorraus
lightwaver
Auch ein Codeschnipsel mit ein paar Kommentaren wäre hilfreich!!!
Gibst doch nicht dass sich hier noch noch nie wer mit dem fast-PWM Mode befasst hat...
Bitte bitte Helft mir...
danke lightwaver
Hallo,
Sehe mahl die doc2466.pdf (Atmega16)
Zuerst die Timer/Counter1 taktfrequenz definieren mittels den PRESCALER.
PRESCALER: Seite 112, Tabelle 48, Register TCCR1B, bits0-2: CS10/CS11/CS12
000 = Timer/Counter1 angehalten
001 = clkio/1 = 16Mhz/1 = 16MHz = 62,5ns pro stufe (dies heisst: NO PRESCALING)
010 = clkio/8 = 16Mhz/8 = 2MHz = 0,5us pro stufe (PRESCALING)
001 = clkio/64 = 16Mhz/64 = 250KHz = 4us pro stufe (PRESCALING)
... usw
PDF Seite 101:
"The PWM resolution for fast PWM can be fixed to 8-, 9-, or 10-bit or defined by either ICR1 or OCR1A"
Guck mahl Seite 111, Tabelle 47:
Mode 5: (Fast PWM) 8-bit
Mode 6: (Fast PWM) 9-bit
Mode 7: (Fast PWM) 10-bit
Mode 14: (Fast PWM) ICR1
Mode 15: (Fast PWM) OCR1A
Mit 8-bit zahlt Timer/Counter immer von 0 bis 255
Mit 9-bit zahlt Timer/Counter immer von 0 bis 511
Mit 10-bit zahlt Timer/Counter immer von 0 bis 1023
Da kann man probieren ob ein Kombination mit PRESCALER die gewunsten periode von 75us gewahlt werden kann.
Ich wurde folgendes machen.
- Nutze mahl ICR1 als periode (Mode 14)
Mode14 = bits WGM13/WGM12/WGM11/WGM10 in Register TCCR1B und TCCR1A = 1110
- selektiere prescaler 001 (clkio/8 = 0,5us pro stufe) dass rechnet einfacher
- ICR1 soll 149 sein, denn Timer/Counter1 zahlt dann von 0 bis zum 149 = 150 stufen (150 * 0,5us = 75us) und fangt nach stufe 149 (TOP) wieder bei stufe 000 (BOTTOM) an.
(siehe Seite 107, Figur 51, 3e signal von oben)
- OCR1A soll 99 sein damit ein puls von 25us entsteht (stufe 99 bis zum stufe 149 = 50 stufen * 0,5us = 25us).
- Register TCCR1A bits 7 und 6 COM1A1/COM1A0 = 11 damit pin OC1A hoch geht bei stufe 98->99 und niedrich geht bei stufe 149->000
(Seite 109, Tabelle 44)
Pin OC1A = pin nummer 19.
Ich hab obenstehendes nicht ausprobiert aber im prinzip sollte es so gehen.
gruss
Henk
Cool danke... werd ich gleich ausprobieren....
Vielen Dank
lightwaver
Ja scheint zu funktionieren (nach dem ton zu urteilen) - muss es erst mit Oszi testen hab momentan nur Lautsprecher angeschlussen damit man hört überhaupt was kommt...
kleiner Fehler is mir aufgefallen: Prescaler auf /8 is 010 nicht 001
Danke auf jeden Fall werd jetzt dann gleich mit Oszi (auf der uni) ausprobieren ...
Vielen Danke nochmal...
lightwaver
Hast du ja recht...kleiner Fehler is mir aufgefallen: Prescaler auf /8 is 010 nicht 001
dachte ja immer ich sei Perfekt (snif)
gruss
Henk
Habs jetzt mit Oszi getestet und es funktioniert tadellos... habs auch ohne Prescaler ausprobiert...
mfg
lightwaver
Wahnsinn, da hat jemand genau das gleiche Problem wie ich!
Also ich habe auch einen Mega16 und möchte den FAST-PWM nutzen. Zunächst aber eine Verständniss Frage: Der FAST-PWM sollte doch eigentlich doppelt so schnenn wie der normale PWM sein, oder?
Hier folgt mein Code:
Das Ergebniss hab ich mir dann auf dem Oszi angesehen und es ist wunderbar:Code:#include <avr/io.h> #include <inttypes.h> #include <avr/interrupt.h> #include <avr/signal.h> SIGNAL (SIG_OUTPUT_COMPARE1A) {} //Noch nicht genutzte Interrupts SIGNAL (SIG_OUTPUT_COMPARE1B) {} void timerinit(void) { TCCR1A = (1<<WGM11) | (1<<WGM10) | (1<<COM1A1) | (1<<COM1B1) | (1<<WGM12); // 10 Bit Fast PWM, OC1A/B ist output nicht invertiert; TCCR1B = (1<<CS11); //Prescaler = 16 //---------------------REGISTER FÜR TIMER_COMPARE_INTERRUPT--// TIMSK = (1<<OCIE1A) | (1<<OCIE1B); //INTERUPT TIFR = (1<<OCF1A) | (1<<OCF1B); //-----------------------------------------------------------// OCR1A = 512; OCR1B = 512; } int main(void) { timerinit(); DDRD = 0xff; PORTD = 0xff; for(;;){}; }
Der Cycle beträgt 50%
Die Periodendauer ist ungefähr 2,2 ms
Nur Leider passiert das ganze unabhängig davon, ob ich "WGM12" im Register TCCR1A setze oder nicht. Meiner Meinung nach, sollte genau dieses Bit den PWM auf Fast-PWM umschalten. An der Periodendauer ändert sich allerdings garnix.
Ich muss zugeben, dass ich mich noch nicht durch das ganze Datenblatt gequält habe, aber ich dachte die wichtigsten Register glesen/gesetzt zu haben.
Falls ihr sonst noch verbesserungsvorschläge zu meinem Code habt, nur zu, ich bin erst seit 2 Tagen an C dran.
Schonmal ein Dankeschön im Voraus.
MFG Moritz
www.free-webspace.biz/update
Hi Ich hab mir deinen Code nicht angegschaut...
Ich hab selber grad viel Hacke für die uni....
Zur 1. Frage: Ja sicher im Fast PWM Mode Zählt er nur hinauf (bis TOP)und fängt dann wieder bei BOTTOM an.
Hingegen beim Phase Correct PWM Zählt er hinauf und dann wieder hinunter... --> prinzipiell kann er doppelt so schnell zählen... (so verstehst auch ich)
Ich kann dir nur sagen wie ichs gelöst hab.
Ich hab ihn im Mode 14 von 0 bis ICR1 (bei mir 1199) zählen lassen...
Beim Output Compare sprich (OCR1A bei mir = 799) schaltet er den Ausgang auf High.
Interrupts braucht man dafür keine !
zum vergleich mein Code:
wie ich die Bits genau gesetzt habe musst dir selber raussuchen ich hab das ganze auf zetteln.... ich muss das mal schön schreiben aber hab jetzt keine Zeit...Code:int main() { // initialize 16-Bit_Timer for fast_PWM TCCR1A = 0xC2; //init Timer TCCR1B = 0x19; OCR1A = 799; //Toggle Value ICR1 = 1199; //Top Value // initialize PD5-PORT for output DDRD |= (1<<PD5); for(;;) { } }
Ich hoff das Hilft dir weiter....
mfg lightwaver
Hm, also ich werde es morgen mal testen, scheint so, dass ich "WGM12" im falschen Register gesetzt habe.
Ich wollte das ganze im Mode 7 betreiben.
MFG Moritz
www.free-webspace.biz/update
Lesezeichen