Forum: Mikrocontroller und Digitale Elektronik STM32F4 DAC Wave Player gibt Rauschen aus


von Tobi89 (Gast)


Lesenswert?

Hallo,

ich habe folgendes Problem mit einem STM32F407:

Es soll ein Teil eines Wave-Files per DAC und DMA für ca. 2 Sekunden 
ausgegeben werden. Der Teil des Files hat aktuell ca. 40kByte und steht 
für Testzwecke in der File1_Table im Programmcode.

Am DAC Pin ist vor dem Lautsprecher noch ein Verstärker vom Typ TPA3123 
angeschlossen.

Die Ausgabe des Sinus in Sine12bit funktioniert einwandfrei. Wenn aber 
die File1_Table verwendet wird (BufferSize und Timer Period wurden 
selbstverständlich angepasst), gibt der Controller ein Rauschen aus. Im 
Hintergrund hört man aber etwas von der Melodie.

Da ich bereits einiges ohne nennenswerten Erfolg ausprobiert habe, bin 
ich jetzt eher ratlos woran es liegen könnte.

Hat von euch jemand eine Idee?

Nachfolgend der Programmcode. DAC_Setup, DAC_AudioOut und DAC_Off werden 
in der main aufgerufen.



#include "stm32f4xx.h"
#include "gDef.h"
#include "gVar.h"

/* Includes 
------------------------------------------------------------------*/

#define DAC_DHR12R2_ADDRESS    0x40007414
#define DAC_DHR8R1_ADDRESS     0x40007410
#define DAC_DHR12R1_ADDRESS    0x40007408

const uint16_t Sine12bit[32] =
{ 2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056, 4095, 4056, 3939, 
3750, 3495,
        3185, 2831, 2447, 2047, 1647, 1263, 909, 599, 344, 155, 38, 0, 
38, 155,
        344, 599, 909, 1263, 1647 };

uint16_t File1_Table[] = {
    0x49,0x53,0x46,0x54,0x22,0x00,0x00,0x00,0x4C,0x61,0x76,0x66,0x35,0x35,0x 
2E,0x31,
    0x39,0x2E,0x31,0x30,0x34,0x20,0x28,0x6C,0x69,0x62,0x73,0x6E,0x64,0x66,0x 
69,0x6C,
    0x65,0x2D,0x31,0x2E,0x30,0x2E,0x32,0x34,0x29,0x00,0x64,0x61,0x74,0x61,0x 
96,0xD8,
    0x00,0x00,0x97,0xFE,0x5C,0x01,0x5F,0x01,0x1E,0x00,0x4F,0x01,0x94,0x00,0x 
E6,0x00,
    0xAE,0x00,0x4C,0x00,0xEF,0xFE,0x82,0x01,0xE4,0x02,0x4C,0x00,0x6C,0xFF,0x 
CE,0xFE,
    0x73,0x01,0x51,0x00,0x0F,0xFF,0x10,0x00,0xF8,0xFE,0xD5,0x00,0x53,0x00,0x 
45,0xFF,
    0xD1,0xFF,0x6C,0x00,0xC9,0xFF,0xDB,0xFF,0xD0,0x01,0xF0,0x00,0x78,0x00,0x 
5F,0xFF,
    0xCF,0xFE,0xDD,0xFF,0xCA,0xFE,0xE4,0xFE,0xBE,0xFF,0x50,0xFF,0x56,0x00,0x 
60,0xFF,
    //...
};




void DAC_Setup(void) {

  /* Preconfiguration before using 
DAC----------------------------------------*/
  GPIO_InitTypeDef GPIO_InitStructure;

  /* DMA1 clock clock enable (to be used with DAC) */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

  /* DAC Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

  /* DAC channel 1 (DAC_OUT = PA.4) configuration */
  GPIO_InitStructure.GPIO_Pin = DAC_RTDS_UC_SIGNAL;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  //Pins für externen Verstärker
  GPIO_InitStructure.GPIO_Pin = AMPLIFIER_GAIN0 | AMPLIFIER_SHUTDOWN
      | AMPLIFIER_GAIN1 | AMPLIFIER_MUTE;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* TIM6 Configuration 
------------------------------------------------------*/
  TIM6_Config();

  /* Wave generator -----------------------------------------------*/
  DAC_Ch1_WaveConfig();
}

/**
 * @brief  TIM6 Configuration
 * @param  None
 * @retval None
 */
void TIM6_Config(void) {
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  /* TIM6 Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);

  /* Time base configuration */
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_Period = 0x290;
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);

  /* TIM6 TRGO selection */
  TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);

}

/**
 * @brief  DAC  Channel1 Wave Configuration
 * @param  None
 * @retval None
 */
void DAC_Ch1_WaveConfig(void) {
  DMA_InitTypeDef DMA_InitStructure;


  /* DAC channel1 Configuration */
  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
  DAC_Init(DAC_Channel_1, (DAC_InitTypeDef*) &DAC_InitStructure);

  /* DMA1_Stream5 channel7 configuration 
**************************************/
  DMA_DeInit(DMA1_Stream5);
  DMA_InitStructure.DMA_Channel = DMA_Channel_7;
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) 
DAC_DHR12R1_ADDRESS;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &File1_Table;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStructure.DMA_BufferSize = 40000;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = 
DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA1_Stream5, &DMA_InitStructure);

}

void DAC_AudioOut(void) {

  // TIM6 enable counter
  TIM_Cmd(TIM6, ENABLE);

  // Enable DMA1_Stream5
  DMA_Cmd(DMA1_Stream5, ENABLE);

  // Enable DAC Channel1
  DAC_Cmd(DAC_Channel_1, ENABLE);

  // Enable DMA for DAC Channel1
  DAC_DMACmd(DAC_Channel_1, ENABLE);




  //Für externen Verstärker:
  //Shutdown disabled (Pin 1)
  GPIO_SetBits(GPIOC, GPIO_Pin_1);

  //MUTE OFF (Pin 3), GAIN0 = 0 (Pin 0), GAIN1 = 0 (Pin 2)
  GPIO_ResetBits(GPIOC, GPIO_Pin_3 | GPIO_Pin_0 | GPIO_Pin_2);
}

void DAC_Off(void) {
  //Externer Verstärker:
  //MUTE ON
  GPIO_SetBits(GPIOC, AMPLIFIER_MUTE);

  //GAIN0 = 0 (Pin 0), GAIN1 = 0 (Pin 2)
  GPIO_ResetBits(GPIOC,
      AMPLIFIER_SHUTDOWN | AMPLIFIER_GAIN0 | AMPLIFIER_GAIN1);



  DAC_Cmd(DAC_Channel_1, DISABLE);

  DAC_DMACmd(DAC_Channel_1, DISABLE);

  DMA_Cmd(DMA1_Stream5, DISABLE);

  TIM_Cmd(TIM6, DISABLE);
}

von c-hater (Gast)


Lesenswert?

Tobi89 schrieb:

> Die Ausgabe des Sinus in Sine12bit funktioniert einwandfrei. Wenn aber
> die File1_Table verwendet wird (BufferSize und Timer Period wurden
> selbstverständlich angepasst), gibt der Controller ein Rauschen aus. Im
> Hintergrund hört man aber etwas von der Melodie.

Falsches Waveformat (signed) als Quelle verwendet?

von Jim M. (turboj)


Lesenswert?

Ich sehe File1_Table deklariert als uint16_t aber mit Werten, deren 
Bereich nur uint8_t abdeckt. Falsch konvertiert?

von Tobi89 (Gast)


Lesenswert?

@c-hater:

das Format ist PCM, mono, 8kHz. Also das Wave Format mit den niedrigsten 
Anforderungen. Sollte passen.

@Jim Meba:

Die Werte in File1_Table sollten nicht das Problem sein. Wenn diese zehn 
mal so groß sind, kommt immer noch ein Rauschen aus den Lautsprechern.

von Uwe B. (derexponent)


Lesenswert?

@Tobi89,

WAV-Daten sind "signed-Werte" müssen also auch so behandelt werden

von Tobi89 (Gast)


Lesenswert?

Ok. Das werde ich dann mal ausprobieren.

von Tobi89 (Gast)


Lesenswert?

Die Umstellung der Wave Werte in signed-Werte hat das Rauschen leider 
nicht beseitigt.

Hat jemand weitere Ideen?

von ADC (Gast)


Lesenswert?

>Die Umstellung der Wave Werte in signed-Werte hat das Rauschen leider
>nicht beseitigt.

Es reicht nicht das Array anstatt als unsigned als signed zu 
deklarieren.

Die DAC-Register sind sicherlich als unsigned deklariert, d.h. der 
Compiler konvertiert den signed Wert wieder nach unsigned und gibt 
bestenfalls eine Warning aus.

Vielleicht solltest du mal alle signed-Werte in unsigned-Werte 
konverieren indem du 0x8000 dazu addierst und das Ergebnis dann durch 2 
teilst (mit 32 Bit rechnen !).

Wenn in der Wave-Datei eine 0 steht, wird dann die halbe 
Versorgungsspannung am DAC ausgegeben, bei -32767 dann enstrechend 0V 
und bei +32767  VCC.

von c-hater (Gast)


Lesenswert?

Tobi89 schrieb:

> das Format ist PCM, mono, 8kHz. Also das Wave Format mit den niedrigsten
> Anforderungen. Sollte passen.

Nicht unbedingt. Den springenden Punkt (signed oder nicht) hast du damit 
immer noch nicht beantwortet.

Allerdings ist 8Bit-Wav meist unsigned, das würde also prinzipiell 
passen.

Allerdings nutzt du damit bloß einen klitzekleinen Bereich des 
DA-Wandlers aus, der ja offensichtlich 12Bit verarbeitet.

Du musst also die Quelldaten zumindest noch auf 12Bit "aufblasen", 
sprich: mit 16 multiplizieren.

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.