Forum: Compiler & IDEs PWM-Konfigurationsprobleme beim Mega 8!


von Mad M. (madang)


Lesenswert?

Hallo,
irgendwie bringe ich das Zeug's nicht zum Laufen.
Möchte für beliebige Pin's (an denen jeweils LEDs hängen) bei Überlauf 
(IR) des Timer1, ein Toggeln realisieren. Also ganz normal bei Überlauf 
(ganz ohne Vergleich ...).
Das zweite Mal beim Vergleich einen IR bewerkstelligen, eigentlich eine 
Phasenkorrektem PWM mit Timer 1.
Nur die Konfig. macht mir ein wenig Probleme. Vielleicht könnt ihr den 
Code richtig stellen.
Für den Mega 16 bzw. 32 gibt es genug Beispielprogramme. Leider nicht 
für den Mega 8.
Danke
Mad


Code:

#include <avr/io.h>
#include <avr/interrupt.h>
// Mega 8L
// Timer/Counter1 Overflow
ISR (TIMER1_OVF_vect)
{
  PORTD ^= (1 << PD2);  // PD2 toggeln
}

// Timer/Counter1 Compare
ISR (TIMER1_COMP_vect)
{
  PORTD ^= (1 << PD0);  // PD2 toggeln
}
int main()
{

 DDRD |= (1 << PD2) | (1 << PD0);
 PORTD |= (1 << PD2) | (1 << PD0);
// ***************************
// Konfig. PWM
// ***************************
 TIMSK |= (1 << OCIE1B) | (1 << TOIE1);                  // IRQ bei 
Compare Match
 OCR1BH = 128;                           // Vergleichswert einstellen
 OCR1BL = 0;
 sei();                                       // IRQs enable (Interrupt 
global einschalten)
 TCCR1A |= (1 << WGM11);          // CTC-Modus (Vergleichmodus)
 TCCR1B |= (1 << CS11);             // Prescaler: 1/8 (zB.: CPU-Takt 
8000000/ Teiler 8)

 while (1) // endlos
 {
     // von hier aus möchte ich die Helligkeit steuern


 }
 return 0;
}

von Karl H. (kbuchegg)


Lesenswert?

Madang Madang schrieb:

> Möchte für beliebige Pin's (an denen jeweils LEDs hängen) bei Überlauf
> (IR) des Timer1, ein Toggeln realisieren. Also ganz normal bei Überlauf
> (ganz ohne Vergleich ...).
> Das zweite Mal beim Vergleich einen IR bewerkstelligen, eigentlich eine
> Phasenkorrektem PWM mit Timer 1.

Hä?

> Für den Mega 16 bzw. 32 gibt es genug Beispielprogramme. Leider nicht
> für den Mega 8.

Weil das beim Mega8 im Prinzip alles völlig identisch ist.


> // Timer/Counter1 Compare
> ISR (TIMER1_COMP_vect)

Da muss aber logisch gesehen noch etwas fehlen.
Da der Timer 2 Compare Register hat, A und B, gibt es auch 2 Interrupt 
Vektoren dafür.
   TIMER1_COMPA_vect      für einen Compare Match am Register OCR1A
   TIMER1_COMPB_vect      für einen Compare Match am Register OCR1B

Hat sich dein Compiler den nicht beschwert, dass mit 'TIMER1_COMP_vect' 
etwas nicht stimmen kann?

>  OCR1BH = 128;                           // Vergleichswert einstellen
>  OCR1BL = 0;

Sicher?
Du willst einen Vergleichswert von 32768?

Schreib das doch so

  OCR1B = 32768;

dann muss keiner im Kopf die Zerlegung in Highbyte und Lowbyte machen 
(bzw. die Umkehrung) um zu wissen, was denn nun der Verlgeichswert ist. 
Mach dir doch nicht selbst das Leben schwer mit etwas, was dir der 
Compiler abnehmen kann. Der gibt dir ein Pseudoregister OCR1B, in das du 
Zuweisen kannst und der Compiler erledigt für dich die Aufteilung in 
OCR1BH und OCR1BL

>  TCCR1A |= (1 << WGM11);          // CTC-Modus (Vergleichmodus)

Wie funktioniert denn der CTC Modus?
Wenn dir das klar ist, ist dir auch klar, was in deiner Konfiguration 
noch fehlt.

>  while (1) // endlos
>  {
>      // von hier aus möchte ich die Helligkeit steuern

da der Compare Match von Register OCR1B abhängt, wirst du halt einfach 
an OCR1B andere Werte zuweisen müssen.

FAQ Punkt 11

PS: Die ISR würde ich anders schreiben.
Im Overflow die LED explizit einschalten
Im COmpare Match explizit ausschalten

Mit dem Toggeln verschleierst du die PWm ein wenig. Wenn irgendwas nicht 
stimmt, dann blinkt deine LED nur mit unterschiedlichen Frequenzen, du 
hast aber keine PWM mehr. Da ziehe ich es vor, auch zu sehen, dass die 
PWM ausgefallen ist, als dass die LED auf halber Helligkeit mit 
unterschiedlichen Frequenzen blinkt.

von Mad M. (madang)


Lesenswert?

Hallo, danke für deine Hilfe. Hat mich sehr weiter gebracht!
Der Compare (TIMER1_COMPB_vect) Modus funktioniert jetzt. LED an Pin D0 
wird abwechselt hell/dunkel, wenn ich die Werte am Register OCR1B 
ändere.
Wenn ich das richtig verstanden habe, steht der untere Wert in Register 
TCNT1 und der obere Wert in Register OCR1B. Zwischen diesen beiden 
Werten zählt der Timer 1.
Leider tut sich an Pin D2 nichts. Egal ob ich an OCR1B od. TCNT1 etwas 
ändere. Kann man im "Timer Overflow" -Modus keinen untere bzw. oberen 
Wert eingeben. Zählt der immer stur von 0 - 65535, setzt den IR und 
fängt wieder bei 0 an.
Oder fehlt an der Konfig. noch etwas?
Danke Mad

von Karl H. (kbuchegg)


Lesenswert?

Madang Madang schrieb:

> Wenn ich das richtig verstanden habe, steht der untere Wert in Register
> TCNT1

Nö.
TCNT1 ist das Zählregister.

Der untere Wert ist immer 0

> und der obere Wert in Register OCR1B.

Jep.

> Zwischen diesen beiden
> Werten zählt der Timer 1.

No. Im CTC Modus zählt der Timer bis zum Wert in OCR1A
Steht doch ziemlich eindeutig im FAQ Link den ich dir gegeben habe und 
natürlich auch im Datenblatt. Den FAQ Link hab ich dir gegeben, weil 
dort eine mehr oder weniger Schritt für Schritt Anleitung gegeben ist, 
wie man sich aus dem Datenblatt die Werte zusammensucht, die man braucht 
und wo man sinnvollerweise im Datenblatt anfängt.

von Mad M. (madang)


Lesenswert?

super danke, habe den Link leider überlesen...
jetzt verstehe ich den ablauf und die konfig. ist jetzt klar.
vielen dank nochmals
mad

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.