Forum: Mikrocontroller und Digitale Elektronik WAV von 8bit auf 7bit


von Markus (Gast)


Lesenswert?

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?

von Philipp B. (philipp_burch)


Lesenswert?

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;

von Markus (Gast)


Lesenswert?

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.

von Markus (Gast)


Lesenswert?

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;
}

von Markus (Gast)


Lesenswert?

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!

von Philipp B. (philipp_burch)


Lesenswert?

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 ;)

von Karl H. (kbuchegg)


Lesenswert?

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
Noch kein Account? Hier anmelden.