mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PWM beim Atmega8


Autor: Thomas L. (tom)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo mitsammen. Ich hoffe ich nerve nicht mit meiner Fragerei, aber ich
habe Probleme damit, die 3 PWM Kanäle des Atmega8 zu nutzen.

Was ich bisher habe:
Um die PWM zu nutzen, sind die Bits WGM10, WGM11, WGM12, WGM13
zuständig. Und hier schon die erste Frage:
* Die Bits 10,11 sind im TCCR1A, die Bits 12,13 im TCCR2A. Ich würde
gerne den 8bit - Modus nutzen (0...255), also muss:
WGM10 -> 0
WGM11 -> 1
WGM12 -> 0
WGM13 -> 0
Nur nun meine Frage: Wohin muss ich denn dann den Wert schreiben, mit
welchem verglichen wird - OCR1A?, OCR1B? Das wär dann wohl der erste
PWM Kanal.

Für den 2ten PWM Kanal ist wohl TCCR2 zuständig.
D.h.
WGM20 -> 1
WGM21 -> 0  -> Ebenfalls wieder eine 8bit PWM
Und wieder die Frage - Wohin muss ich den wert schreiben und an welchem
Pin erhalte ich das Ausgangssignal? OCR2?

Und die dritte Frage: WO ist der 3te Kanal? Ein WGM3x finde ich nicht
.. ebensowenig wie ein WGM0x

Ich danke euch für eure Hilfe :)

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast doch gerade 3 PWM-Kanäle aufgezählt:
OCR1A
OCR1B
und
OCR2

Und vermutlich kommen die Vergleichswerte auch in die OC-Register
(output compare register...).

Bei OCR1A und OCR1B wird für beide Timer1 als Zeitbasis genommen.
Für OCR2 ist die Basis Timer2.

Autor: Thomas L. (tom)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh mein Gott.
Irgendwie muss ich blind gewesen sein :) Mich hat das TCCR1x komplett
irritiert. Heißt das, dass OCR1A und OCR1B immer im gleichen Modus
laufen (Sprich: 8Bit, ..) auch wenn ich nur das TCCR1A/B
dementsprechend nur einmal setze?
Das heisst OC1A, OC1B und OC2 sind meine Ausgänge?

Bin noch recht neu bei der ganzen Sache - Danke mal für deinen Input :)

Autor: bla (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
du musst auch noch die COM1Ax und COM1Bx Register setzen - sonst kommt
nix.

Für Phase correct PWM (8,9 oder 10 Bit) würde ich folgendes nehmen:

WGM13: 1 z.B. 8 Bit Phase correct PWM
WGM12: 0
WGM11: 0
WGM10: 0

COM1A1: 1 Ausgabe an OC1A und OC1B
COM1A0: 0 hochzählen:zurücksetzen
COM1B1: 1 runterzählen: setzen
COM1B0: 0

Wenn du dann in OCR1AL "255" reinschreibst bekommst du am Pin
OC1A 5V, bei "0" 0V - an OC1B kannst du OCR1BL ausgeben.

Autor: bla (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die WGM-Werte die du oben beschrieben hast sind nach meinem Datenblatt
für 9-Bit PWM

Autor: Thomas L. (tom)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
so .. die WGM habe ich geändert. Im Datenblatt des atmega8 muss WGM10 =
1 sein, der Rest = 0 für eine 8bit PWM.

Ich habe jetzt:
---snip---
#include <avr/io.h>
#include <stdint.h>

int main(void)
{
  // Set 8 bit Phase correct PWM Mode for channel 1 + 2(A/B)
  TCCR1A |=  (1 << WGM10);  // 8bit Phase correct CH1
  TCCR1A &= ~(1 << WGM11);  // 8bit Phase correct CH1
  TCCR1B &= ~(1 << WGM12);  // 8bit Phase correct CH2
  TCCR1B &= ~(1 << WGM13);  // 8bit Phase correct CH2

  // Clock select channel 1+2
  TCCR1B |=  (1 << CS10);
  TCCR1B &= ~(1 << CS11);

  // Connect output Pin channel 1
  TCCR1A &= ~(1 << COM1A0);
  TCCR1A |=  (1 << COM1A1);

  // Connect output Pin channel 2
  TCCR1A &= ~(1 << COM1B0);
  TCCR1A |=  (1 << COM1B1);


  // Set 8 bit phase correct PWM Mode for channel 3
  TCCR2 |=  (1 << WGM20);
  TCCR2 &= ~(1 << WGM21);

  // Clock select channel 3
  TCCR2 |= (1 << CS20);
  TCCR2 &= ~(1 << CS21);

  // Connect output Pin channel 3
  TCCR2 &= ~(1 << COM20);
  TCCR2 |= (1 << COM21);


  // Now the values can be put into OCR1A, OCR1B, OCR2
  OCR1AL = 0;
  OCR1BL = 255;
  OCR2 = 126;



  while(1);
}
---snip---

Aber noch immer nix am Pin :(

Autor: The Engineer (the_engineer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
*abo

Autor: Kersten Decker (unbenannt-editor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!
Setze mal die entsprechenden Ports als Ausgang....dadrüber bin ich eben
auch gerade gestolpert....

Habe aber auch ein Problem mit atmega8 und PWM: Laut PDF soll er 16 Bit
PWM mit Timer1 können, also 2 PWM-Kanäle (OCR1A und OCR1B) mit je 16 Bit
PWM. Ich bekomme nur 10 Bit PWM hin.

Gruß
Kersten

Autor: Kersten Decker (unbenannt-editor)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
So, bei mir klappts jetzt:

//Pins als Ausgang gesetzt
TCCR1A |= _BV(COM1A1) | _BV(COM1B1); // Eigenschaften der Portpins

TCCR1A |= _BV(WGM11); // 16 Bit Fast PWM, TOP ist ICR1:
TCCR1B |= _BV(WGM12);
TCCR1B |= _BV(WGM13);

ICR1H = 0xFF; //Top = 0xFFFF;
ICR1L = 0xFF; //Normalerweise über ein TEMP-Register schreiben, aber da
der Timer noch nicht läuft sollte das nicht nötig sein

TCCR1B |= _BV(CS10); // kein Prescaler und Timer starten

OCR1A = 0xFFFF; //5V
OCR1B = 0x7FFF; //die Hälfte


@Tom: Was hat es sich denn mit OCR1AL und OCR1AH auf sich? Erscheint
logisch aber steht nirgendwo im Datenblatt. Ich verwende einfach nur
OCR1A/B und es klappt.

Kersten

Autor: Sebastian (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Datenblatt steht auf Seite 79, dass man bei den 16 bit Registern erst 
die das high byte beschrieben werden muss, bevor das low byte 
geschrieben wird. Gilt allerdings auch nur bei assembler. Wenn ihr C 
programmiert, macht das der Compiler selbstständig. Deswegen geht das 
auch wenn man direkt OCR1A/B beschreibt.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
@Sebastian:
Was soll das denn bitteschön wieder? Wenn die das nach zwei Jahren nicht 
rausgefunden haben, nützt es jetzt auch nichts mehr!

Autor: neu-avr (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
@Johannes M. (johnny-m)
es gibt immer wieder Menschen denen hilft es trotzdem weiter, egal wie 
alt der Beitrag ist.

@Sebastian: Danke !

Gruß,

Autor: Julian Tauscher (Firma: Stuttgart) (livingevil)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kersten D. schrieb:
> So, bei mir klappts jetzt:
>
> //Pins als Ausgang gesetzt
> TCCR1A |= _BV(COM1A1) | _BV(COM1B1); // Eigenschaften der Portpins
>
> TCCR1A |= _BV(WGM11); // 16 Bit Fast PWM, TOP ist ICR1:
> TCCR1B |= _BV(WGM12);
> TCCR1B |= _BV(WGM13);
>
> ICR1H = 0xFF; //Top = 0xFFFF;
> ICR1L = 0xFF; //Normalerweise über ein TEMP-Register schreiben, aber da
> der Timer noch nicht läuft sollte das nicht nötig sein
>
> TCCR1B |= _BV(CS10); // kein Prescaler und Timer starten
>
> OCR1A = 0xFFFF; //5V
> OCR1B = 0x7FFF; //die Hälfte


Hi,

ich hab nur mittel viel Ahnung: Wenn ich den Code in eine int main(void)
{ } einfüge, müsste doch am Port OC1A bzw. -B eine LED Leuchten, ohne 
dass ich etwas dem Code hinzufügen muss (etwa eine while Schleife) oder 
fehlt da noch etwas?

Danke und sorry, dass ich hier die Totenruhe störe ;)

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Julian T. schrieb:
> oder
> fehlt da noch etwas?

Bin jetzt nicht über den ganzen Code gegangen, aber du musst natürlich 
noch die Portpins für OC1A und OC1B auf Ausgang setzen. Das wären beim 
Mega8 PB1 und PB2.

Autor: Chris F. (chfreund) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe mir gerade auch den PWM via Timer/Counter im Datenblatt angesehen 
und den Code minimal angepasst, so dass er direkt lauffähig ist. 
Vielleicht hilft es ja jemandem.
An Pin 15/16 sollte je eine LED mit Vorwiderstand, schon geht es los:
// Dieses Makro verwende ich nicht mehr, hilft vielleicht den Rest des Threads zu verstehen
//#define _BV(a) ((1 << a))
// Mein AtMega8 läuft mit 4MHz
#define F_CPU 4000000UL
// Wartezeit in der Schleife auf 5us
#define INTERVALL 5UL
// Minimalwert 1000h
#define MINVALPWM 0x1000
// IO-Makros 
#include <avr/io.h>
// hier gibt es die tollen delay-Funktionen
#include <util/delay.h>

int main(void)
{
  DDRB |= (1<<DDB1);  //Pin 15 ist ein Ausgang
  DDRB |= (1<<DDB2);  //Pin 16 ist ein Ausgang
  /* Im folgenden wird die Pulsweitenmodulation für Timer/Counter1 eingestellt
  wir wollen eine schnelle Pulsweitenmodulation, Maximalwert (Top) in ICR1*/
  TCCR1A |= (1<<(COM1A1)) | (1<<(COM1B1)); // OC1A und OC1B beim Raufzählen an (bezieht sich auf den internen PWM)
  TCCR1A |= (1<<(WGM11)); // Timer/Counter1 Control Register A - Waveform Generator Modus 11 
  TCCR1B |= (1<<(WGM12));  // Timer/Counter1 Control Register B - Waveform Generator Modus 12
  TCCR1B |= (1<<(WGM13)); // Timer/Counter1 Control Register B - Waveform Generator Modus 13
  ICR1 = 0xFFFF;      //ICR1, alle Bits setzen
  TCCR1B |= (1<<(CS10)); // kein Prescaler (clkio wird 1:1 vom IC-Takt übernommen), Timer starten
  
  uint_fast16_t n = MINVALPWM;  // 16-Bit-Variable für die Dimmschleife
    while (1) 
    {
  OCR1A = 0xFFFF;      //5V an Pin 15
    for (;n<0xffff;n++)  //von MINVALPWM bis 2^16 raufzählen
      {
        OCR1B = n;  // Intensität setzen
        _delay_us(INTERVALL);  //5us Pause
      }
  OCR1A = 0;      //0V an Pin 15
    for (;n>MINVALPWM;n--)    //von 2^16 bis MINVALPWM runterzählen
      {
        OCR1B = n;  // Intensität setzen
        _delay_us(INTERVALL);  //5us Pause
      }
    }
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.