cancel
Showing results for 
Search instead for 
Did you mean: 

DAC maximum sampling rate of STM32F407

Willunen
Associate III

In AN4566 the maximum sampling rate of the DAC of a STM32F407 is claimed to be 10.5 Msps but I'm not able to get any faster than 7 Msps before it starts to skip samples.

The clock of the STM32F407 is set to 168 MHz.

TIM8 triggers the DAC via TRGO.

DAC1 is setup to do simultaneous conversions and therefore receives 32bit words on DAC1->DHR12RD.

DMA uses LL_DMA_STREAM_5, LL_DMA_CHANNEL_7, is setup in double buffer mode (and thus circular)

DMA1_Stream5_IRQHandler has ample time to do its job so that isn't a problem. (I use GPIOE_0 to see the processing time on an oscilloscope.)

Any idea where I have gone wrong?

here are the relevant (I think) parts of the code :

DMA:
 
LL_DMA_SetChannelSelection(DMA1, LL_DMA_STREAM_5, LL_DMA_CHANNEL_7);
 
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_STREAM_5, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
 
LL_DMA_SetStreamPriorityLevel(DMA1, LL_DMA_STREAM_5, LL_DMA_PRIORITY_VERYHIGH);
 
LL_DMA_SetMode(DMA1, LL_DMA_STREAM_5, LL_DMA_MODE_CIRCULAR);
 
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_STREAM_5, LL_DMA_PERIPH_NOINCREMENT);
 
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_STREAM_5, LL_DMA_MEMORY_INCREMENT);
 
LL_DMA_SetPeriphSize(DMA1, LL_DMA_STREAM_5, LL_DMA_PDATAALIGN_WORD);
 
LL_DMA_SetMemorySize(DMA1, LL_DMA_STREAM_5, LL_DMA_MDATAALIGN_WORD);
 
LL_DMA_EnableDoubleBufferMode(DMA1, LL_DMA_STREAM_5);
 
LL_DMA_SetPeriphAddress(DMA1, LL_DMA_STREAM_5, (uint32_t) &DAC1->DHR12RD);
 
LL_DMA_SetMemoryAddress(DMA1, LL_DMA_STREAM_5, (uint32_t) &dac_buffer_a[0]);
 
LL_DMA_SetMemory1Address(DMA1, LL_DMA_STREAM_5, (uint32_t) &dac_buffer_b[0]);
 
LL_DMA_SetDataLength(DMA1, LL_DMA_STREAM_5, STEPS);
 
LL_DMA_EnableIT_TC(DMA1, LL_DMA_STREAM_5);
 
LL_DMA_EnableStream(DMA1, LL_DMA_STREAM_5);
 
 
 
DAC:
 
LL_DAC_InitTypeDef DAC_InitStruct = {0};
 
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DAC1);
 
DAC_InitStruct.TriggerSource = LL_DAC_TRIG_EXT_TIM8_TRGO;
 
DAC_InitStruct.WaveAutoGeneration = LL_DAC_WAVE_AUTO_GENERATION_NONE;
 
DAC_InitStruct.OutputBuffer = LL_DAC_OUTPUT_BUFFER_DISABLE;
 
LL_DAC_Init(DAC, LL_DAC_CHANNEL_1, &DAC_InitStruct);
 
LL_DAC_Init(DAC, LL_DAC_CHANNEL_2, &DAC_InitStruct);
 
 
LL_DAC_EnableTrigger(DAC1, LL_DAC_CHANNEL_1);
 
LL_DAC_EnableTrigger(DAC1, LL_DAC_CHANNEL_2);
 
LL_DAC_EnableDMAReq(DAC1, LL_DAC_CHANNEL_1);
 
LL_DAC_EnableDMAReq(DAC1, LL_DAC_CHANNEL_2);
 
LL_DAC_Enable(DAC1, LL_DAC_CHANNEL_1);
 
LL_DAC_Enable(DAC1, LL_DAC_CHANNEL_2);
 
 
 
IRQ:
 
void DMA1_Stream5_IRQHandler(void)
 
{
 
   static uint32_t phase = 0;
 
   uint16_t x;
 
   LL_GPIO_SetOutputPin(GPIOE, LL_GPIO_PIN_0);
 
   if (LL_DMA_IsActiveFlag_TC5(DMA1))
 
   {
 
      LL_DMA_ClearFlag_TC5(DMA1);
 
      if (LL_DMA_GetCurrentTargetMem(DMA1, LL_DMA_STREAM_5))
 
      {
 
         for (x = 0; x < STEPS; x++)
 
         {
 
            dac_buffer_a[x] = waveform[phase >> 22];
 
            phase += stepsize;
 
         }
 
      }
 
      else
 
      {
 
         for (x = 0; x < STEPS; x++)
 
         {
 
            dac_buffer_b[x] = waveform[phase >> 22];
 
            phase += stepsize;
 
         }
 
      }
 
   }
 
   LL_GPIO_ResetOutputPin(GPIOE, LL_GPIO_PIN_0);
 
}

15 REPLIES 15

The DAC does output a reasonable 1 MHz sinewave. It isn't a pretty one as it is constructed by just 7 samples from the sinewave-table.0690X00000ARba2QAD.jpg

See the image I uploaded. I don't think the DAC is overclocked. The datasheet states "Max frequency for a correct DAC_OUT change when small variation in the input code (from code i to i+1LSB)" So I cannot complain with ST when the output isn't correct anymore.

The load of the DAC is 0 (zero) ohm as it is connected directly to the negative input of the (external) opamp with the positive input on (virtual) ground. Therefore there is no problem with any capacitive loading. (see AN4566)

With timer-triggered-DMA you'd still have precise feed, except with some jitter. Given the DAC's output won't follow exactly the data input anyway, it may well be the jitter won't matter.

The choice is of course yours.

JW

> The load of the DAC is 0 (zero) ohm

You mean, zero Siemens... ;)

JW

Timer-triggered mode does help. I now use TIM8_UP to trigger DMA2 and I can almost get it to work at 9 MHz, so now I have settled for 8 MHz. Thanks for the suggestion, I wouldn't have thought about doing it this way. One question though, why does this give some jitter?

Wilko

Beacuse of the collisions with other busmasters, and potentially collisions within the DMA module itself.

If you can ensure that neither processor core nor other DMA nor other busmaster accesses the memory you are using as data source nor the the APB1 bus, this might perhaps be jitter-free.

JW