cancel
Showing results for 
Search instead for 
Did you mean: 

DAC waveform generation with DMA not working

marcogrossi89
Associate II
Posted on November 27, 2014 at 15:45

I am using the STM32L Discovery Board (STML152RB chip on board). The IDE is Emblocks. I was trying to generate a sawtooth wave signal using DAC and DMA but it does not work. I was able to make the same program without DMA (by triggering an interrupt at regular time with a timer and updating the DAC value inside the interrup handler) but with DMA it does not work. Below is the code I use. Anyone can help to fix it?

#include ''stm32l1xx_conf.h''

#include <stm32l1xx.h>

#include <stm32l1xx_rcc.h>

#include <stm32l1xx_gpio.h>

#include <stm32l1xx_tim.h>

#include <stm32l1xx_dac.h>

#include <stm32l1xx_dma.h>

#include <misc.h>

#include <math.h>

#define WAVE_FREQ 5000

#define WAVE_POINTS 100

#define TIMER_PERIOD 9

uint16_t wave_array[100];

uint8_t j;

float pi_greco = 3.14159;

int timervalue;

void GPIO_initialize(void)

{

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    GPIO_InitTypeDef gpioStructure;

    gpioStructure.GPIO_Pin = GPIO_Pin_5;

    gpioStructure.GPIO_Mode = GPIO_Mode_AIN;

    GPIO_Init(GPIOA, &gpioStructure);

}

void DAC_initialize(void)

{

RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

RCC_APB1PeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

DMA_DeInit(DMA1_Channel1);

DMA_InitTypeDef DMA_Structure;

    DMA_Structure.DMA_PeripheralBaseAddr = (uint32_t) &DAC->DHR12R2;

    DMA_Structure.DMA_MemoryBaseAddr = (uint32_t) &wave_array;

    DMA_Structure.DMA_DIR = DMA_DIR_PeripheralDST;

    DMA_Structure.DMA_BufferSize = WAVE_POINTS;

    DMA_Structure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

    DMA_Structure.DMA_MemoryInc = DMA_MemoryInc_Enable;

    DMA_Structure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

    DMA_Structure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

    DMA_Structure.DMA_Mode = DMA_Mode_Circular;

    DMA_Structure.DMA_Priority = DMA_Priority_High;

    DMA_Structure.DMA_M2M = DMA_M2M_Disable;

    DMA_Init(DMA1_Channel1, &DMA_Structure);

    DAC_InitTypeDef DAC_Structure;

DAC_Structure.DAC_Trigger = DAC_Trigger_T6_TRGO;

DAC_Structure.DAC_WaveGeneration = DAC_WaveGeneration_None;

DAC_Structure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;

DAC_Init(DAC_Channel_2, &DAC_Structure);

    DMA_Cmd(DMA1_Channel1, ENABLE);

    DAC_DMACmd(DAC_Channel_2, ENABLE);

DAC_Cmd(DAC_Channel_2, ENABLE);

}

void TIM6_initialize(void)

{

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);

TIM_TimeBaseInitTypeDef timerInitStructure;

timerInitStructure.TIM_Prescaler = 319;

timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;

timerInitStructure.TIM_Period = TIMER_PERIOD;

timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseInit(TIM6, &timerInitStructure);

TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);

TIM_Cmd(TIM6, ENABLE);

}

int main(void)

{

    for(j=0; j<100; j++)

        {

        wave_array[j] = (uint16_t)(500 + 20*j);

        }

    GPIO_initialize();

    TIM6_initialize();

    DAC_initialize();

  while(1)

  {

  }

}

9 REPLIES 9
stm322399
Senior
Posted on November 27, 2014 at 15:58

According RM0038, DAC_channel2 trigs DMA1_channel3. I do not catch why DAC_ch2 is associated with TIM7, but if I were you I will use TIM7 instead of TIM6.

Or you can use the DAC_Channel1/TIM6/DMA1_Channel2 combination as well.

marcogrossi89
Associate II
Posted on November 27, 2014 at 16:10

Changed DMA_Channel1 with DMA_Channel3 and TIM6 with TIM7 but again it is not working

stm322399
Senior
Posted on November 27, 2014 at 16:22

Does it still work with TIM7 and no DMA ?

marcogrossi89
Associate II
Posted on November 27, 2014 at 18:15

Yes. It works also with TIM7. However with the no DMA version there is also another difference: the event that triggers the DAC update is TIM_IT_Update with no DMA and 

TIM_TRGOSource_Update with DMA (since this was used in a code I found on the web).

Posted on November 27, 2014 at 18:16

#include ''stm32l1xx_conf.h''
#include <
stm32l1xx.h
>
#include <
stm32l1xx_rcc.h
>
#include <
stm32l1xx_gpio.h
>
#include <
stm32l1xx_tim.h
>
#include <
stm32l1xx_dac.h
>
#include <
stm32l1xx_dma.h
>
#include <
misc.h
>
#include <
math.h
>
#define WAVE_FREQ 5000
#define WAVE_POINTS 100
#define TIMER_PERIOD 10
uint16_t wave_array[100];
uint8_t j;
float pi_greco = 3.14159;
int timervalue;
void GPIO_initialize(void)
{
GPIO_InitTypeDef gpioStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
gpioStructure.GPIO_Pin = GPIO_Pin_5;
gpioStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &gpioStructure);
}
void DAC_initialize(void)
{
DMA_InitTypeDef DMA_Structure;
DAC_InitTypeDef DAC_Structure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
DMA_DeInit(DMA1_Channel3); // DAC2 -> DMA1 Ch3
DMA_Structure.DMA_PeripheralBaseAddr = (uint32_t) &DAC->DHR12R2;
DMA_Structure.DMA_MemoryBaseAddr = (uint32_t) &wave_array[0];
DMA_Structure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_Structure.DMA_BufferSize = WAVE_POINTS;
DMA_Structure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_Structure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_Structure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_Structure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_Structure.DMA_Mode = DMA_Mode_Circular;
DMA_Structure.DMA_Priority = DMA_Priority_High;
DMA_Structure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel3, &DMA_Structure);
DAC_Structure.DAC_Trigger = DAC_Trigger_T6_TRGO;
DAC_Structure.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_Structure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DAC_Init(DAC_Channel_2, &DAC_Structure);
DMA_Cmd(DMA1_Channel3, ENABLE);
DAC_DMACmd(DAC_Channel_2, ENABLE);
DAC_Cmd(DAC_Channel_2, ENABLE);
}
void TIM6_initialize(void)
{
TIM_TimeBaseInitTypeDef timerInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
timerInitStructure.TIM_Prescaler = 320-1;// 32MHz -> 100KHz
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = TIMER_PERIOD - 1; // DIV10, 100KHz -> 10KHz
timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM6, &timerInitStructure);
TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
TIM_Cmd(TIM6, ENABLE);
}
int main(void)
{
for(j=0; j<100; j++)
{
wave_array[j] = (uint16_t)(500 + 20*j);
}
GPIO_initialize();
TIM6_initialize();
DAC_initialize();
while(1)
{
}
}

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
stm322399
Senior
Posted on November 27, 2014 at 18:41

RCC_APB1PeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

of course this is the best candidate to explain why it does not work.

marcogrossi89
Associate II
Posted on November 28, 2014 at 10:17

Used the code suggested by clive1 and also fixed the RCC statement

RCC_AHB1PeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

with

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

but the code still does not work.

Posted on November 28, 2014 at 13:46

Yes did this all blind, I don't have any boards/scopes with me right now.

Could confirm timer is firing using TIM interrupt and/or toggling LED or pin.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
marcogrossi89
Associate II
Posted on November 28, 2014 at 17:36

Now it seems to work. I have found some code on the web and replicated it with minor changes. Following is the working code. Moved to TIM2 but I do not think this is the problem. Maybe DAC definition should be made just after GPIO definition and both defined after DMA definition. Not sure.

#include ''stm32l1xx_conf.h''

#include <stm32l1xx.h>

#include <stm32l1xx_rcc.h>

#include <stm32l1xx_gpio.h>

#include <stm32l1xx_tim.h>

#include <stm32l1xx_dac.h>

#include <stm32l1xx_dma.h>

#include <misc.h>

#include <math.h>

#define WAVE_FREQ 5000

#define WAVE_POINTS 100

#define TIMER_PERIOD 10

#define DAC_DHR12RD_Address      0x40007420

uint16_t wave_array[100];

uint16_t j;

float pi_greco = 3.14159;

int timervalue;

void DAC_initialize(void)

{

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);

    GPIO_InitTypeDef gpioStructure;

    gpioStructure.GPIO_Pin = GPIO_Pin_5;

    gpioStructure.GPIO_Mode = GPIO_Mode_AIN;

    GPIO_Init(GPIOA, &gpioStructure);

    DAC_InitTypeDef DAC_Structure;

DAC_Structure.DAC_Trigger = DAC_Trigger_T2_TRGO;

DAC_Structure.DAC_WaveGeneration = DAC_WaveGeneration_None;

DAC_Structure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;

DAC_Init(DAC_Channel_2, &DAC_Structure);

DAC_Cmd(DAC_Channel_2, ENABLE);

    DAC_DMACmd(DAC_Channel_2, ENABLE);

}

void DMA_initialize(void)

{

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

DMA_DeInit(DMA1_Channel3);

DMA_InitTypeDef DMA_Structure;

    DMA_Structure.DMA_PeripheralBaseAddr = DAC_DHR12RD_Address;

    DMA_Structure.DMA_MemoryBaseAddr = (uint32_t) &wave_array;

    DMA_Structure.DMA_DIR = DMA_DIR_PeripheralDST;

    DMA_Structure.DMA_BufferSize = WAVE_POINTS;

    DMA_Structure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

    DMA_Structure.DMA_MemoryInc = DMA_MemoryInc_Enable;

    DMA_Structure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

    DMA_Structure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

    DMA_Structure.DMA_Mode = DMA_Mode_Circular;

    DMA_Structure.DMA_Priority = DMA_Priority_High;

    DMA_Structure.DMA_M2M = DMA_M2M_Disable;

    DMA_Init(DMA1_Channel3, &DMA_Structure);

    DMA_Cmd(DMA1_Channel3, ENABLE);

}

void TIM2_initialize(void)

{

   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    TIM_TimeBaseInitTypeDef timerInitStructure;

timerInitStructure.TIM_Prescaler = 320-1;

timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;

timerInitStructure.TIM_Period = TIMER_PERIOD-1;

timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseInit(TIM2, &timerInitStructure);

TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);

TIM_Cmd(TIM2, ENABLE);

}

int main(void)

{

    for(j=0; j<100; j++)

        {

        wave_array[j] = (uint16_t)(2000 + 1500*sin((2*pi_greco*j)/100));

        // wave_array[j] = (uint16_t)(500+20*j);

        }

    DMA_initialize();

    DAC_initialize();

    TIM2_initialize();

  while(1)

  {

  }

}