www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PWM - OCR1A ändert nichts?


Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Ich versuche gerade per PWM Töne auf einem Lautsprecher zu erzeugen. Die 
Tonhöhe würde ich dabei gerne über den OCR1 Wert verändern (Benutze 
einen ATMega16 und Timer1).

So initialisiere ich den Timer:

TCCR1A = (1<<WGM11)|(1<<WGM10)|(1<<COM1A1);
TCCR1B = (1<<CS11) ;
OCR1A = 0x0515;

Aber egal was ich in OCR1A schreibe, der Ton bleibt immer der gleiche 
:-(
Woran kann das liegen?

Autor: Erklärer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PWM ändert, wie der Name schon sagt, nur das Tastverhältnis, die 
Freuqenz bleibt gleich. Die du unterschiedliche Tonhöhen haben willst 
musst du das anders machen, z.B. CTC Mode

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was genau ist denn der CTC Mode? Im AVR GCC Tutorial kann ich da auf 
anhieb nix finden :-(

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:
> Was genau ist denn der CTC Mode?

CTC
Clear Timer on Compare

Bei erreichen eines bestimmten Zählerstandes, den du vorgeben
kannst, wird der Timer wieder auf 0 gesetzt.

> Im AVR GCC Tutorial kann ich da auf
> anhieb nix finden :-(

Dann wirds Zeit den mal auszuprobieren. CTC funktioniert fast
so wie der Overflow eines Timers. Nur dass du die Zahl vorgibst
an der dieser 'Overflow' ausgelöst werden soll, bei der
der Timer wieder auf 0 gesetzt wird. Ach ja. Der Interrupt
heist auch anders.

PS: Im AVR Gcc Tutorial wirst du über viele Bereiche deines
Prozessors nichts finden. Deshalb ist es auch so wichtig,
das Datenblatt seines Prozessors zur Hand zu haben. Dieses
Datenblatt kann man bei Atmel downloaden.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Interrupt hab ich bisher garnicht benutzt, da gibt es ja einen extra 
output pin für's PWM.
Heißt das also ich mach jetzt einen Interrupt in dem ich einen 
bestimmten Pin umschalte, und stelle dann ein wie oft dieser Interrupt 
aufgerufen wird?
Hab ich das richtig verstanden? ;-)

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, habe mal im Datenblatt nachgesehen. Leider kommt jetzt garnichts 
mehr aus dem Speaker (der nun an PortB hängt).
Hier die Timerinitialisierung:

TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS12);
OCR1A = 0x0015;

Und der Interrupt:

ISR(TIMER1_COMPA)
{
    PORTB = 255-PORTB;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:
> Interrupt hab ich bisher garnicht benutzt, da gibt es ja einen extra
> output pin für's PWM.

Schon. Aber PWM macht ja ganz was anderes.

> Heißt das also ich mach jetzt einen Interrupt in dem ich einen
> bestimmten Pin umschalte, und stelle dann ein wie oft dieser Interrupt
> aufgerufen wird?
> Hab ich das richtig verstanden? ;-)

So in etwa könnte man das sagen.
Du schreibst eine ISR (eine Interrupt Service Routine).
Diese ISR wird aufgerufen, wenn bestimmte Bedingungen
oder Ereignisse eintreten. Ein derartiges Ereignis ist
zb. das der Timer seinen vorgegebenen Wert erreicht hat
und jetzt auf 0 zurückgesetzt wird.

Darüber müsste es im Gcc Tutorial aber einen Abschnitt
geben.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:
> So, habe mal im Datenblatt nachgesehen. Leider kommt jetzt garnichts
> mehr aus dem Speaker (der nun an PortB hängt).
> Hier die Timerinitialisierung:
>
> TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS12);
> OCR1A = 0x0015;
>
> Und der Interrupt:
>
> ISR(TIMER1_COMPA)
> {
>     PORTB = 255-PORTB;
> }

Da fehlt aber noch einiges.
Es gibt in einem AVR viele Interrupt Quellen. Du musst also
entscheiden welche Interrupts zugelassen werden und welche
nicht. Und du musst die Interrupts generell freigeben.

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe jetzt noch

TIMSK |= (1 << OCIE1A);

hinzugefügt, aber das half leider auch nichts :-(

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:
> Habe jetzt noch
>
> TIMSK |= (1 << OCIE1A);
>
> hinzugefügt, aber das half leider auch nichts :-(

hast du einen
  sei();
gemacht?

...

int main()
{
   ....
   .... alles initialisieren
   ....

   sei();   // ab jetzt können Interrupts zuschlagen

   while( 1 ) {
      ....
   }
}

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
yep, hab ich....

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcel wrote:
> yep, hab ich....


Und?
Zeigst du jetzt endlich mal dein Programm so wie es jetzt ist,
oder sollen wir weiter raten, was eventuell nicht stimmen könnte?

Autor: Marcel (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Oh, Entschuldigung. Hier ist das Programm

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da fällt mir gleich mal auf

ISR(TIMER1_COMPA)

Der Name des Interrupts ist falsch. Interrupt Namen enden
immer auf '_vect', also kann das schon mal nicht TIMER1_COMPA
heissen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TCCR1B = (1<<WGM12)|(1<<WGM13)|(1<<CS12);
  TIMSK |= (1 << OCIE1A);
  OCR1A = 0x0015;


Wenn du WGM12 und WGM13 setzt, dann gilt als Topwert nicht
OCR1A sondern ICR1.

Quelle: Siehe Datenblatt

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.