PWM Sinus 440 Hz funktioniert nicht

Gast #1232001
Hallo

ich habe hier einen ATmega8 @ 16 Mhz.


Mit diesem möchte ich ein 440 Hz Sinussignal per PWM ausgeben.

Timer 2 ist auf fast PWM geschaltet.

Es wird vorher eine Tabelle mit 20 verschiedenen Sinuswerten berechnet.


Der Timer1 COMPA Interrupt gibt der PWM jeweils den nächsten berechneten 
Sinuswert. Dieser Interrupt wird alle T=1/(440Hz*20 Schritte) ausgelöst.

Somit sollte an OC2 ein 440 Hz Sinussignal anliegen.

Leider habe ich kein Scope hier sondern nur einen Lautsprecher. Der 
Ausgang geht an 2 Transistoren (Endstufe) und von dort aus an den 
Lautsprecher. Es ist nichts zu hören.


Vielleicht kann mit ja jemand von euch helfen. Ich bedanke mich schonmal 
im vorraus.


Hier der Code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <math.h>
4

5
#define pi 3.1415926
6

7
void init(void);
8

9
unsigned int anzahlWerte=20;
10
unsigned char sinusWerte[20];
11

12
unsigned int step=0;
13

14
ISR(TIMER1_COMPA_vect)
15
{
16
    OCR1AL=sinusWerte[step];
17
  step++;
18
  if(step==20) step=0;
19
}
20

21

22

23
int main(void)
24
{
25

26
  init();
27
  while(1);
28
  return 0;
29
}
30

31
void init(void)
32
{
33
  int i;
34
  for(i=0;i<anzahlWerte;i++)
35
    sinusWerte[i]=(unsigned char)(127.5+127.5*sin(2.0*pi*i/anzahlWerte));
36
  DDRB=0b00001000;    // PWM Ausgang OC2
37
  TCCR2=(1<<WGM21)|(1<<WGM20)|(1<<COM21)|(1<<CS20);  // Fast PWM, non invertig mode, no prescaler
38
  OCR2=128;  // Lautsprecher aus: PWM auf 50%
39
  
40
  TCCR1A=(1<<WGM12);  // CTC
41
  TCCR1B=(1<<CS11);  // CLK/8
42
  OCR1AL=227;      // Entspricht Sinus mit ca 440 Hz
43
  sei();
44
}
Gast
Einen Fehler habe ich entdeckt.


Im Interrupt muss es natürlich

OCR2=sinusWerte[step];

statt

OCR1AL=sinusWerte[step];

heißen.


Leider funktioniert es trotzdem noch nicht.
Gast
So, noch ein Fehler; ich hatte den Interrupt nicht aktiviert.


TIMSK=(1<<OCIE1A);


habe ich in der init() Funktion hinzugefügt.

Der Ausgang wird an einer LED getestet und es leuchtet mit ca 1,5 Hz.


Um diesen jetzt auf 440 Hz zu bringen muss TCNT1 beim Aufruf des 
Interrupt resettet werden.


Ich dachte dies würde durch
1
TCCR1A=(1<<WGM12);  // CTC
 passieren. Leider macht ers nicht. Vielleicht kann mir jemand sagen was 
ich falsch gemacht habe?
Gast
Hallo! Danke soweit.

Hab alles umgeändert. Ändert aber nichts daran, dass TCNT1 nicht 
gelöscht wird. Ich bin soweit der 440 Hz Ton ausgeben zu können:

ISR(TIMER1_COMPA_vect)
{
  TCNT1=0;
    OCR2=sinusWerte[step];
  step++;
  if(step==20) step=0;
}


Ich dachte durch das

TCCR1A=(1<<WGM12);  // CTC

wäre TCNT1=0; unnötig. Leider wird TCNT1 nur gelöscht wenn ich es selber 
in den Interrupt reinschreibe. Dann sind auch die 440 Hz zu hören.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.