Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing DMA for DAC #50

Open
jacky4566 opened this issue Dec 11, 2019 · 2 comments
Open

Implementing DMA for DAC #50

jacky4566 opened this issue Dec 11, 2019 · 2 comments

Comments

@jacky4566
Copy link

jacky4566 commented Dec 11, 2019

So it seems that calls to the DAC take quite a bit of time so I would like to implement DMA transfers.

I tried my hand to use your DMA library but I cant seem to get it to fire. My code will complile but nothing happens :/

DMA feeding DAC code:

#include "stm32l4_dma.h"

stm32l4_dma_t stm32l4_DAC_DMA;

static int DACresolution = 12;

uint32_t i;

uint32_t DAC_DMA_OPTION = DMA_OPTION_MEMORY_TO_PERIPHERAL |
                          DMA_OPTION_PERIPHERAL_DATA_SIZE_32 |
                          DMA_OPTION_MEMORY_DATA_SIZE_32 |
                          DMA_OPTION_MEMORY_DATA_INCREMENT |
                          DMA_OPTION_PRIORITY_MEDIUM ;

void setup() {
  Serial.begin(9600);
  while (!Serial) {}
  analogWriteResolution(DACresolution);
  analogWrite(PIN_DAC0, i);
  analogWrite(PIN_DAC1, i);

  DAC->CR = (uint32_t) DAC->CR | 0x3000; //enable DAC DMA and underrun

  stm32l4_dma_create(&stm32l4_DAC_DMA, DMA_CHANNEL_DMA1_CH3_DAC1, DMA_OPTION_PRIORITY_LOW);
  stm32l4_dma_enable(&stm32l4_DAC_DMA, NULL, NULL);
}

void loop() {
  i = (i + 64) & DAC_DHR12R1_DACC1DHR;

  stm32l4_dma_start(&stm32l4_DAC_DMA, (uint32_t)&DAC->DHR12R1,(uint32_t)i, 1, DAC_DMA_OPTION);    //This should trigger a DMA trandfer to the DAC->DHR12R1 register.
 
}
@jacky4566 jacky4566 changed the title DAC Speed under 1Khz Implementing DMA for DAC Dec 14, 2019
@GrumpyOldPizza
Copy link
Owner

Almost there ;-)

First off, you should be using circular DMA instead of oneshot. Use the half-done / full-done to implement a simple double buffered scheme.

In DAC->CR, you need to enable an external trigger (no underrun or such). The external trigger (TSEL) should be set to TIM7_TRIG. TIM7 is used for Tone()/noTone(), so it seems appropriate to use that one.

You can look at the stm32l4_wiring_tone.c code to see how it's kind of used, except you don't need to interrupt callback.

@jacky4566
Copy link
Author

jacky4566 commented Dec 14, 2019

Thanks for the help GrumpyOldPizza.
Still a bit stuck here. I was trying one shot mode just to get things working but circular mode also doesn't seem to be helping.

I have implement the Timer7 at 1MHZ and enabled the appropriate TSEL and TEN1. The DAC appears to be working off that source now. Plugging values into the second channel (DHR12R2) transfer correctly.

With a circular DMA how does it know when to do transfers? Do i need to point the Timer 7 to the DMA as well?

Here is the code so far.

#include "stm32l4_dma.h"
#include "stm32l4_timer.h"

stm32l4_dma_t stm32l4_DAC_DMA;
stm32l4_timer_t stm32l4_DAC_timer;

static int DACresolution = 12;

uint32_t desiredValue;

uint32_t DAC_DMA_OPTION = DMA_OPTION_MEMORY_TO_PERIPHERAL |
                          DMA_OPTION_CIRCULAR |
                          DMA_OPTION_PERIPHERAL_DATA_SIZE_32 |
                          DMA_OPTION_MEMORY_DATA_SIZE_32 |
                          DMA_OPTION_PRIORITY_MEDIUM ;

void setup() {
  Serial.begin(9600);
  analogWriteResolution(DACresolution);
  analogWrite(PIN_DAC0, 0); //use board manager to setup dac
  analogWrite(PIN_DAC1, 0); //use board manager to setup dac

  //Setup timer 7 to trigger arbitraty 1MHz (@80MHZ)
  stm32l4_timer_create(&stm32l4_DAC_timer, TIMER_INSTANCE_TIM7, NULL, 0);
  stm32l4_timer_enable(&stm32l4_DAC_timer, (stm32l4_timer_clock(&stm32l4_DAC_timer) / 4000000) - 1, 4 - 1, TIMER_OPTION_COUNT_PRELOAD, NULL, NULL, 0);
  
  //Setup DMA to transfer into DAC
  stm32l4_dma_create(&stm32l4_DAC_DMA, DMA_CHANNEL_DMA1_CH3_DAC1, DMA_OPTION_PRIORITY_MEDIUM);
  stm32l4_dma_enable(&stm32l4_DAC_DMA, NULL, NULL);
  stm32l4_dma_start(&stm32l4_DAC_DMA, (uint32_t)&DAC->DHR12R1, (uint32_t)desiredValue, 1, DAC_DMA_OPTION);

  //enable DAC DMA, Trigger on TIM7, Timer trigger EN
  DAC->CR = (uint32_t) DAC->CR | 0x1014;

  //start timer
  stm32l4_timer_start(&stm32l4_DAC_timer, false);
}

void loop() {
  desiredValue = desiredValue + 64;
  DAC->DHR12R2 = desiredValue; //Verify operation on channel 2
  delay(100); //keep things slow
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants