Forum: Mikrocontroller und Digitale Elektronik Tiny45 und PWM


von Michael M. (moonuser)


Lesenswert?

Hallo,
ich versuche mit TC 0 eine PWM an Ausgang PB1 zu erzeugen.
Im Simulator als auch in der Testschaltung, passiert an PB 1 gar nichts.
Kann mir jemand sagen, was noch konfiguriert werden muss?
das programm habe ich erst mal abgekürzt.
Für die 3 Ints sind routinen vorhanden.

Wäre nett, wenn sich das jemand anschauen könnte.

Vielen Dank!
1
MCUCR|=(1<<PUD);
2
  DDRB=(1<<PB1); //Ausgang PWM
3
  
4
  TCCR0A=((1<<WGM00)|(1<<WGM01)|(1<<COM0B0));
5
  
6
  TCCR0B=((1<<CS01)); //Vorteiler 8
7
  OCR0A=127;  //50 %output für Start
8
  OCR0B=127;
9
  
10
  
11
  TIMSK|=((1<<OCF0A)|(1<<OCF0B)|(1<<TOV0)); //Int ein
12
  TIFR|=((1<<OCF0A)|(1<<OCF0B)|(1<<TOV0));
13
  sei();

  while(1);

von Jörg G. (joergderxte)


Lesenswert?

Dir ist klar, dass:
 - es min. 1000 Takte(127*8) dauert, bis da was passiert? (Falls du's 
nur im "Single Step mode" probiert hast)
 - "toggle on compare match" (nicht an- oder aus- sondern um- 
schalten, bei erreichen des OC0X-Werts) für PWM relativ ungünstig ist? - 
wahrscheinlich willst du "Clear on compare match".
 - die Bits im Register "TIMSK" nicht so heißen wie in deinem Code, 
sondern "OCIE0A", "OCIE0B", "TOIE0" (Das sollte aber bei diesem AVR 
nichts ausmachen, deine falschen Namen sind an der richtigen Stelle) ?
 - du auch die passenden ISRs brauchst, wenn du die Interrupts 
aktivierst (Die PWM funktioniert auch ohne die Interrupts)?
 - du 'PB0' nicht auf Ausgang geschaltet hast (der Ausgang für OC0A)?
 - du ALLE Pull-ups abgeschaltet hast?
 - du das TIFR-Register gar nicht anfassen musst, wenn du den Prescaler 
(TCCR0B) erst am Ende der Initialisierung (direkt vor dem 'sei()') 
setzt?

Und was heißt "in der Testschaltung passiert an PB1 gar nichts"? Wie 
stellst du das fest?

hth, Jörg

von Michael M. (moonuser)


Lesenswert?

Hallo Jörg,

 - es min. 1000 Takte(127*8) dauert, bis da was passiert? (Falls du's
nur im "Single Step mode" probiert hast)

<< Auto step und habe schon gewartet, bis der counter ein paar mal 
hochgezählt hat.


 - "toggle on compare match" (nicht an- oder aus- sondern um-
schalten, bei erreichen des OC0X-Werts) für PWM relativ ungünstig ist? -
wahrscheinlich willst du "Clear on compare match".
<< Ich habe den Fast PWM Mode gesetzt.
Soweit ich es verstanden habe, wird der Ausgang bei erreichen gesetzt 
und am Überlauf (Bottom) rückgesetzt



 - du auch die passenden ISRs brauchst, wenn du die Interrupts
aktivierst (Die PWM funktioniert auch ohne die Interrupts)?

<< wie oben geschrieben, sind diese vorhanden und werden auch 
aufgerufen.

 - du 'PB0' nicht auf Ausgang geschaltet hast (der Ausgang für OC0A)?

<< ich verwende OC0B, daher PB1

 - du ALLE Pull-ups abgeschaltet hast?

<< ja war ein versuch

 - du das TIFR-Register gar nicht anfassen musst, wenn du den Prescaler
(TCCR0B) erst am Ende der Initialisierung (direkt vor dem 'sei()')
setzt?

<< wusste ich nicht

Und was heißt "in der Testschaltung passiert an PB1 gar nichts"? Wie
stellst du das fest?

<<Oszi
,
Grüße Michael

von Jörg G. (joergderxte)


Lesenswert?

>> - "toggle on compare match" (nicht an- oder aus- sondern um-
>> schalten, bei erreichen des OC0X-Werts) für PWM relativ ungünstig ist? -
>> wahrscheinlich willst du "Clear on compare match".
> Ich habe den Fast PWM Mode gesetzt.
Da haben wir beide nicht richtig gelesen ;)
Aber nur COM0X0=1 ist in dem Datenblatt, das ich gerade anschaue, bei 
"Fast-PWM-mode" 'reserved'.
Probier mal:
1
  TCCR0A=((1<<WGM00)|(1<<WGM01)|(1<<COM0B1));
2
  //  Clear on OC0B on compare match     ^
> Ich verwende OC0B
Warum richtest du dann OC0A ein?

hth, Jörg

von Michael M. (moonuser)


Lesenswert?

Hallo

die Initialisierung sieht nun so aus (nach deinen Anregungen)
1
DDRB=(1<<PB1|1<<PB4|1<<PB0); //Ausgang PWM
2
  
3
  TCCR0A=((1<<WGM00)|(1<<WGM01)||(1<<COM0B1)|(1<<COM0B0));
4
  
5
  TCCR0B=((1<<CS01)); //Vorteiler 8
6
  OCR0A=127;  //50 %output für Start
7
  OCR0B=127;
8
  
9
  
10
  TIMSK|=((1<<OCIE0A)|(1<<OCIE0B)|(1<<TOIE0)); //Int ein
11
  
12
  sei();
Nur (1<<OCIE0B) habe ich auch getestet.
Ich verwende den Timer doppelt, daher auch die Interrupts, die aber 
nicht stören dürften.
Testweise habe ich sie ebend deaktiviert.- Keine Änderung.

Michael

von Jörg G. (joergderxte)


Lesenswert?

Dann bin ich auch ratlos, also die Routinefragen :
Funktioniert die Schaltung sicher (d.h. du kannst den Pin dauerhaft 
ein/ausschalten, mit Warteschleife togglen, im Interrupt togglen) ?
Kannst du das ganze Programm posten ?
Hast du irgendwelche Compilerwarnungen? (evtl. brauchst du noch "-Wall" 
"-Wextra", falls da was kommt)
Flashst du die richtige Datei ;) ? (Meistens sind's ja doch die 
blödesten Fehler).
Ist der Programmer bei den Tests angeschlossen(bzw. könnte der stören)?

hth, Jörg

von MWS (Gast)


Lesenswert?

Mach mal aus Deinem Code hier:

>> DDRB=(1<<PB1|1<<PB4|1<<PB0); //Ausgang PWM

>>   TCCR0A=((1<<WGM00)|(1<<WGM01)||(1<<COM0B1)|(1<<COM0B0));

das hier:
1
DDRB=((1<<PB1)|(1<<PB4)|(1<<PB0)); //Ausgang PWM
2
  
3
  TCCR0A=((1<<WGM00)|(1<<WGM01)|(1<<COM0B1)|(1<<COM0B0));

Die Klammern erfüllen schon einen gewissen Sinn ;-) Bei der zweiten 
Zeile ist ein || drin, das ist etwas Anderes als ein |
Schalte die Interrupts zum Testen ab.

von Michael M. (moonuser)


Lesenswert?

Hallo,
ja MWS, das
1
 ||
habe ich nicht gesehen und genau das war das Problem.

Aber auf jeden Fall Vielen Dank!


Grüße Michael

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
Noch kein Account? Hier anmelden.