cancel
Showing results for 
Search instead for 
Did you mean: 

noise in dac using dma

julienbld
Associate II
Posted on December 20, 2011 at 10:52

Hello,

I can synthesize a waveform into a buffer, dma transfering it to dac. Result is ok but there's a noise that I can't remove. When the waveform is a 0 signal, the noise is still here. The noise has a frequency (~ dma interrupt freq) it seems to be square like, and seems to be louder when CPU is more used. Am I doing something wrong with dma or dac? The dac pin is directly connected to the amp input, I don't know if I should add some components? Do you know what can cause this noise? I made a simplified source code which can reproduce the error:

#include ''stm32f10x.h''
#define DAC_DHR12RD_Address 0x40007420
/* Init Structure definition */
DAC_InitTypeDef DAC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
uint16_t outbuf[32] = {
2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048,
2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048,
2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048,
2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048};
char
compute_next_frame;
/* Private function prototypes -----------------------------------------------*/
void
RCC_Configuration(
void
);
void
GPIO_Configuration(
void
);
void
Delay(__IO uint32_t nCount);
int
main(
void
)
{
RCC_Configuration();
GPIO_Configuration();
/* TIM2 Configuration */
/* Time base configuration */
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 24;
TIM_TimeBaseStructure.TIM_Prescaler = 30;
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* TIM2 TRGO selection */
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
/* DAC channel1 Configuration */
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DAC_Init(DAC_Channel_1, &DAC_InitStructure);
DMA_DeInit(DMA1_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12RD_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&outbuf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 32;
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_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel3, ENABLE);
DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 
//HIGHEST_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init( &NVIC_InitStructure );
DAC_Cmd(DAC_Channel_1, ENABLE);
DAC_DMACmd(DAC_Channel_1, ENABLE);
/* TIM2 enable counter */
TIM_Cmd(TIM2, ENABLE);
compute_next_frame = 0;
while
(1)
{
while
(!compute_next_frame);
// compute the next frame
// simulate cpu load
// when this block is off there's some noise but less
int
i, j;
for
(i=1;i<2000;i++)
j = 4984131/i;
compute_next_frame=0;
}
}
void
RCC_Configuration(
void
)
{ 
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}
void
GPIO_Configuration(
void
)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
// function called in stm32f10x_it.c by DMA1_Channel3_IRQHandler
void
dma_it(){
if
(DMA_GetITStatus(DMA1_IT_TC3)) {
int
i;
// simulating square signal (1048 / 3048) or 0 signal (2048 / 2048)
if
(outbuf[0]==3048)
for
(i=0; i<32; i++)
outbuf[i] = 2048; 
//1048;
else
for
(i=0; i<32; i++)
outbuf[i] = 2048; 
//3048;
compute_next_frame = 1;
DMA_ClearITPendingBit(DMA1_IT_GL3);
}
}

Julien.
5 REPLIES 5
raptorhal2
Lead
Posted on December 20, 2011 at 16:10

What is the noise level in millivolts at the DAC output ?

Cheers, Hal

julienbld
Associate II
Posted on December 21, 2011 at 10:27

The ''noise'' level is about 1 or 2 mV.

The main problem for me is that it's not a white noise but it has a precise frequency (interrupt dma freq).

Cheers,

Julien.
raptorhal2
Lead
Posted on December 21, 2011 at 22:44

Getting low noise from an analog peripheral in a high speed mostly digital chip is a difficult design problem. The datasheet doesn't give a spec for noise, but other errors are comparable to what you are seeing.

Try disabling the DAC output buffer to see if this built in amplifier is picking up noise.

If all else fails, put in an RC filter either on your external amplifier or between the buffer and external amplifier. It may take a bit of experimentation to get the best balance between filtering noise and keeping sparkling highs in the audio.

Cheers, Hal

julienbld
Associate II
Posted on December 23, 2011 at 17:36

When disabling the DAC output buffer, I can notice two things:

- I have to switch off my halogen lamp and to unplug my laptop from main supply (because of 50hz signal very loud) ;)

- there's no reduction of the noise I try to get rid of.

When not using DMA but CPU to feed the DAC (sample by sample), it seems to give a more ''white'' noise that is less annoying for my application.

I will try an RC filter between microcontroller and amp.

Do you think that using an external DAC (either 12bit or 16bit) could solve the problem by lowering the noise level?

Cheers,

Julien

raptorhal2
Lead
Posted on December 23, 2011 at 23:00

An external DAC can have less noise. The F4 Discovery board has a sound chip, you might consider a design like that. But try filtering first.

Cheers, Hal