Hallo an Alle! Ich möchte eine WAV-Datei abspielen. Dazu benutze ich einen mega32 mit 16MHz, CLK/8 PWM, und Mono 16KHz 8bit WAV-Daten. Um eben die 16KHz hinzubekommen (damit man am Ausgang den PWM nicht mehr hört) möchte ich den PWM auf 7bit einstellen. Das klappt soweit auch wunderbar. Die WAV wird in gewünschter Geschwindigkeit ausgegeben. Jedoch mit Rauschen. Nach einem Blick aufs Oszilloskop sehe ich, dass die obere hälfte meines signals abgeschnitten wird. Um von 8 auf 7 Bit zu kommen habe ich einfach durch 2 geteilt. Das scheint jedoch nicht des rätsels lösung zu sein. Weiss jemand hier was ich tun muss damit ich wieder beide Signalhälften am Ausgang vorfinde?
Hi, zeig' doch mal den betreffenden Code. Ich vermute, es gibt ein Problem mit dem Vorzeichen, da du einen signed Integer nicht direkt dem Timer zuweisen kannst. Eher so:
1 | OCR1 = (a / 2) + 64; |
ARGH! Danke! War ja eigentlich klar... Aber manchmal denkt man einfach nicht nach... Aber, jetzt schneidet er mir beide seiten ab und das Signal erinnert mehr an ein Rechteck.
ISR(TIMER1_OVF_vect) { if(read_position < track_infos[current_track].track_length) OCR1AL = (take_buffer_byte()/2)+64; else read_position = 0; } char take_buffer_byte() { char ret = buffer_pointer[pwm_pointer]; pwm_pointer++; if(pwm_pointer > (BUFFER_SIZE-1)) swap_buffers(); return ret; }
Problem gelöst. Danke für den Tipp mit signed char! Ich habe das jetzt alles auf unsigned gestellt und schon arbeitet die Routine vernünftig. Hört sich toll an!
Markus schrieb: > ISR(TIMER1_OVF_vect) > { > if(read_position < track_infos[current_track].track_length) > OCR1AL = (take_buffer_byte()/2)+64; > else > read_position = 0; > } > > char take_buffer_byte() > { > char ret = buffer_pointer[pwm_pointer]; > pwm_pointer++; > if(pwm_pointer > (BUFFER_SIZE-1)) > swap_buffers(); > return ret; > } Ist 'char' standardmässig signed? Ich denke nicht. Dann funktioniert es natürlich nicht, da der Klammerausdruck dann einen Wertebereich von 0 bis 127 hat, was deine 7 Bit bei einer Addition von 64 überschreitet. Da kommt es nun drauf an, wie deine Daten im Puffer vorliegen. Sind es vorzeichenbehaftete Werte in Zweierkomplementdarstellen (Also einfach signed chars), dann solltest du sowohl Puffer wie auch Funktion damit deklarieren. Wenn es aber fortlaufende Werte von 0 bis 255 sind, dann reicht in der Tat eine einfache Division durch 2. Ausserdem sind Funktionsaufrufe in ISRs nicht so geschickt, da dann jeweils alle Register auf dem Stack gesichert werden müssen. EDIT: Zu spät ;)
Markus schrieb: > char take_buffer_byte() > { > char ret = buffer_pointer[pwm_pointer]; Du solltest dir etwas zur Regel machen: char benutzt du nur, wenn du es mit Texten zu tun hast. Wenn deine Memory-Inhalte einfach nur Bytes sind, dann benutzt du unsigned char. Wenn in diesen Bytes zusätzlich noch ein Vorzeichenbit enthalten ist, dann benutzt du signed char Aber grundsätzlich überlasst du es niemals dem Compiler, ausser bei Texten, ob er einen char als signed oder unsigned ansieht!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.