Hallo zusammen, ich möchte am PIN PA7 eine PWM mit timer0 generieren. Leider bekomme ich überhaupt kein Signal. DDRA |= (1<<PORTA7); // PA7 auf Output // PWM am PIN PA7 aktivieren TOCPMSA1 = (1<<TOCC6S0); TOCPMCOE = (1<<TOCC6OE); // Compare Output Mode, Phase Correct PWM Mode (siehe Tabelle 11-7 auf Seite 87) TCCR0A = (1<<COM0B1); // PWM, Phase Correct (siehe Tabelle 11-8 auf Seite 87) mit TOP OCRA TCCR0A = (1<<WGM00) | (1<<WGM02); // Vorteiler auf 256 => f = CPU_8MHZ/256 TCCR0B |= (1<<CS02); // PWM 50% OCR0A = 127; CPU läuft mit geändert Fusbits mit 8MHz. Bitte um Hilfe und Tipps. Herzlichen DANK
> TCCR0A = (1<<COM0B1); > TCCR0A = (1<<WGM00) | (1<<WGM02); Durch die zweite Zeile wird der Wert aus der ersten überschrieben, also '|=' verwenden.
Unabhängig davon musst Du die betreffenden TOCC-Ausgänge "enablen" Das Register befindet sich bei der Beschreibung der 16-Bit-Timer, TOCPMCOE heißt es.
Vielen Dank für die Hinweise und Tipps. Ich habe den Code korregiert: // PA7 as output DDRA = (1 << PINA7); // configure 8 bit timer0 as PWM TCCR0A = (1 << WGM01) | (1 << WGM00) | (1 << COM0B0); // PWM Modus, non-inverting mode TCCR0B = (1 << CS01); // Prescaler 8 //TOCPMSA0 = (0 << TOCC3S0); TOCPMSA1 = (1<<TOCC6S0); // select TOCC6 (PA7) for output compare OC0B TOCPMCOE |= (1 << TOCC6OE); // enable mux channel output OCR0B = 8; // duty cycle (0...255) Leider immer noch kein Signal am Pin. Woram kann es liegen? werdenhier DDRA Register (siehe PINA7 Bezeichung) und TOCPMSA1 mit TOCPMCOE richtig eingestellt? Danke für die Tipps
Setze mal anstelle COM0B0 das Bit COM0B1. Und TOCPSMA1 muss komplett 0 sein.
Das setzen auf COM0B1 ist leider trotzdem kein Siganl am Pin. Hier nochmal der gesamte Code im Überblick: int main(void) { PUEA &= ~ (1<<PORTA7); // Pull up on PA7 disabled PORTA &= ~ (1<<PORTA7); // PA7 as output DDRA |= (1 << PORTA7); // configure 8 bit timer0 as PWM TCCR0A |= (1 << WGM01) | (1 << WGM00) | (1 << COM0B1); // PWM Modus, non-inverting mode TCCR0B |= (1 << CS01); // Prescaler 8 // select TOCC6 (PA7) for output compare OC0B TOCPMSA0 = 0x00; TOCPMSA1 |= (1<<TOCC6S0) | (1 << TOCC6S1); TOCPMCOE |= (1 << TOCC6OE) ; // enable mux channel output OCR0A = 127; // duty cycle 50% sei(); while(1) { } } Bitte um weitere Hinweise und Tipps
Knut B. schrieb: > Setze mal anstelle COM0B0 das Bit COM0B1. > > Und TOCPSMA1 muss komplett 0 sein. Beides leider ohne Erfolg.
Ich schick nachher noch mal was in ASM, dann kannst Du es ableiten. Grundsätzlich stimmt Dein Code bis auf TOCPSMA1, aber das hattest Du ja noch geändert.
So, wie gesagt. In meiner Anwendung sind alle Timer aktiv, deswegen die entsprechende Init. Timer0 geht mit OCR0B auf TOCC2 raus. Musst Du also passig ändern.
1 | |
2 | ;setup Ports |
3 | ldi Temp, 0b11101011 |
4 | out DDRA, Temp |
5 | ldi Temp, 0b00001000 |
6 | out PortA, Temp |
7 | |
8 | ... |
9 | |
10 | |
11 | ;setup Timer0 (Timebase) |
12 | ldi Temp, (1<<COM0B1)|(1<<WGM01)|(1<<WGM00) |
13 | out TCCR0A, Temp ;Fast PWM, noninverting |
14 | ldi Temp, (0<<CS02)|(0<<CS01)|(1<<CS00) ;Prescaler 1 |
15 | out TCCR0B, Temp |
16 | ldi Temp, 255 ;Charger off |
17 | out OCR0B, Temp |
18 | |
19 | ldi Temp, 0b00000000 ;OC0B routed to TOCC2 output |
20 | sts TOCPMSA0, Temp |
21 | |
22 | |
23 | ldi Temp, 0b11110100 ;TOCC7/TOCC6/TOCC4/TOCC4/TOCC2 output enabled |
24 | sts TOCPMCOE, Temp |
Das:
> DDRA |= (1<<PORTA7); // PA7 auf Output
und das:
ldi Temp, 0b11101011
out DDRA, Temp
passt für micht nicht zusammen.
Wie ist denn PORTA7 bei Dir definiert?
Vielleicht mal mit
DDRA |= (1<<DDA7); // PA7 auf Output
(müsste ja wahrscheinlich
DDRA |= 0b00000001 sein)
ausprobieren.
Werner
Werner schrieb: > DDRA |= (1<<DDA7); // PA7 auf Output > (müsste ja wahrscheinlich > DDRA |= 0b00000001 sein) Nö, 0b10000000.
Knut B. schrieb: > Nö, 0b10000000. Klar. Hab zu schnell geschriebenm. Asche auf mein Haupt. facepalm
Vielen Dank an euch für die Hinweise und Tipps. Jetzt funktioniert es!!! Am Anfang hatte ich Probleme, da der OCR0B Register für die Pulsweite nicht definiert war. Hier nun ein Beispiel mit 122 HZ PWM und 50% duty cycle mit einem Bild als Beweis :-) #include "headerfiles.h" int main(void) { PUEA &= ~ (1<<PORTA7); // Pull up off PORTA &= ~ (1<<PORTA7); // reset Port A7 DDRA |= (1 << DDRA7); // PA7 as output // configure 8 bit timer0 TCCR0A |= (1 << WGM00) | (1 << WGM01) | (1 << COM0B1); // fast PWM Modus, non-inverting mode TCCR0B |= (1 << WGM02); // set TOP counter OCR0A // select TOCC6 (PA7) for output compare OC0B TOCPMSA0 |= 0x00; TOCPMSA1 |= 0x00; // (1<<TOCC6S0) => warum 0x00? TOCPMCOE |= (1 << TOCC6OE); // enable mux channel output (PA7) OCR0A = 255; // PWM Frequenz f = CPU/prescaler/OCR0A = 8000000/1024/255 =~ 122 Hz ~ 8ms OCR0B = 127; // Pulsweite (duty cycle) 50% ~ 4ms TCCR0B |= (1 << CS02); // start timer0 with prescaler 1024 sei(); // enable interrupts while(1) { TO DO... } } Eine Frage hätte ich: Warum muss TOCPMSA1 auf 0x00 gesetzt werden? Welchen Sinn macht dann dieser Register?
In TOCPSMA1 steckt die Kodierung der Timer OCRs für TOCC4 bis TOCC7, in Deinem Fall also auch für TOCC6. Da Du OCR0B verwenden willst, lauten die Bits dafür 00. Da Du andere Timer noch nicht verwendest, ist es klug, auch diese Bits erst einmal auf 0 zu lassen, damit Du nicht zusätzlich verwirrt wirst. Wenn Du andere OCRs verwenden willst, kannst Du die betreffenden Bits selbstverständlich auch manipulieren. Aber einen Schritt nach dem anderen und durch Probieren das Datenblatt verstehen.
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.