DMA problem solved

What are you developing?
stan
Posts: 44
Joined: Wed Nov 11, 2020 7:40 pm

Re: DMA problem

Post by stan »

I know that using 2 timers (based on program such as shown below) I can generate two pulses with any phase shift angle = timer 1- delay(x) - timer 2 , I have no problem with that but I prefer to use program with DMA.

Code: Select all

HardwareTimer pwmtimer3(3);
void setup() {

  pinMode(PA7, PWM);// CH2
pwmtimer3.pause();
  pwmtimer3.setPrescaleFactor(180);
  pwmtimer3.setOverflow(100 - 1);
  pwmtimer3.setCompare(TIMER_CH2, 50);
   pwmtimer3.refresh();
  pwmtimer3.resume();
}

void loop() {
}
 

stan
Posts: 44
Joined: Wed Nov 11, 2020 7:40 pm

Re: DMA problem

Post by stan »

stan wrote:
Fri Nov 20, 2020 1:58 pm
You can generate synchronized pulses using two timers in several ways, please study RM0008 chapter. 15.3.15
I believe this is more for Keil users, I am not familiar with it.

stevestrong
Posts: 390
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 7
Location: Munich, Germany
Contact:

Re: DMA problem

Post by stevestrong »

If you want to use DMA, then try the last alternative method as suggested in my previous post.

ag123
Posts: 517
Joined: Thu Dec 19, 2019 5:30 am
Answers: 1

Re: DMA problem

Post by ag123 »

another way is to use a single timer and use 2 channels and play with the output compare registers, this works as the base frequency will be the same.
the main problem is that that would normally be interrupt based and interrupts is very slow, limiting to no more than a few mhz

stan
Posts: 44
Joined: Wed Nov 11, 2020 7:40 pm

Re: DMA problem

Post by stan »

Thanks for suggestions I will try them, it will take some time for me to do it.

Another matter. How to get square wave instead sine wave in program from post #1 ?

mlundin
Posts: 35
Joined: Wed Nov 04, 2020 1:20 pm
Answers: 2

Re: DMA problem

Post by mlundin »

The signal output on the PWM pin is a square wave. The digital pins can only output 0 or 1, that is 0V or 3.3V for the STM32 processors. This signal becomes an analog signal only after low pass filtering.

stan
Posts: 44
Joined: Wed Nov 11, 2020 7:40 pm

Re: DMA problem

Post by stan »

almost done, just calibration

Code: Select all

#define SAMPLES 77
#include <libmaple/dma.h>
dma_tube_config dma_cfg, dma_cfg2;
int flag = 0;
int flag1 = 0;
int out = PB6;
int out1 = PB8;

int val[SAMPLES];
int val1[SAMPLES];

int16 shift = 0;

int amp = 40;//***************************************
int cnt = 0;
int time_track = 0;
float stp = 6.2831 / SAMPLES;
int ret = 17;

timer_dev *dev = PIN_MAP[out].timer_device;
uint8 cc_channel = PIN_MAP[out].timer_channel;
timer_dev *dev1 = PIN_MAP[out1].timer_device;
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;

void fun()
{
  flag++;
}
void fun1()
{
  flag1++;
}

void timer_conf()
{
  /////////////
  timer_dma_set_base_addr(dev, TIMER_DMA_BASE_CCR2);
  timer_dma_set_burst_len(dev1, 1);
  timer_dma_enable_req(dev, cc_channel1);
  timer_set_reload(dev, 102);
  timer_set_prescaler(dev, 0);
  ///////////////
  timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
  timer_dma_set_burst_len(dev1, 1);
  timer_dma_enable_req(dev1, cc_channel1);
  timer_set_reload(dev1, 102);
  timer_set_prescaler(dev1, 0);
}

void dma_conf()
{
  dma_init(DMA1);
  /* T4C2 DMA C4 */
  dma_cfg.tube_dst = &(dev->regs.gen->DMAR);
  dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
  dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
  dma_cfg.tube_src = val;
  dma_cfg.tube_src = val1;
  dma_cfg.tube_src_size = DMA_SIZE_32BITS;
  dma_cfg.tube_nr_xfers = SAMPLES;
  dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
  dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH1;
  dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
  dma_cfg.target_data = 0;

  ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);
}

void dma_start()
{
  dma_attach_interrupt(DMA1, DMA_CH4, fun);
  dma_enable(DMA1, DMA_CH4);
  timer_resume(dev1);
    dma_enable(DMA1, DMA_CH1);
  dma_enable(DMA1, DMA_CH2);

}

void init_wave()
{
  int i;
  for (i = 0; i < SAMPLES; i++)
  {
   // val[i] = 40 + amp * sin(stp * i);
    val1[i] = 40 + amp * cos(stp * i);
    //////////////

  }
}

void setup()
{
  int i;
  // pinMode(out1, PWM);
  pinMode(out, OUTPUT);
  pinMode(out1, OUTPUT);
  timer_conf();
  dma_conf();
  dma_start();
  init_wave();
}

void loop()

{
  int i;
  /////////////////
  
  for (i = 0; i < SAMPLES; i++)
    //if ( val1[i]  > 40)
    if ( val1[i]  < 38)
    {
      digitalWrite(PB8, HIGH);
    }
    else
    {
      digitalWrite(PB8, LOW);
    }
    
  /////////////////
  for (i = 0; i < SAMPLES; i++)
    //if ( val1[i]  > 40)
    if ( val1[i]  > 38)
    {
      digitalWrite(PB6, HIGH);
    }
    else
    {
      digitalWrite(PB6, LOW);
    }

}

stan
Posts: 44
Joined: Wed Nov 11, 2020 7:40 pm

Re: DMA problem - solved

Post by stan »

Can't get 50% pulses simultaneously on PB6 and PB8, separately pulses are ok 50%

mlundin
Posts: 35
Joined: Wed Nov 04, 2020 1:20 pm
Answers: 2

Re: DMA problem

Post by mlundin »

Probably because you generate them one after the other, try to write to both pins inside the same loop

Code: Select all

  for (i = 0; i < SAMPLES; i++) 
  {
    //if ( val1[i]  > 40)
    if ( val1[i]  < 38)
    {
      digitalWrite(PB8, HIGH);
    }
    else
    {
      digitalWrite(PB8, LOW);
    }
    //if ( val1[i]  > 40)
    if ( val1[i]  > 38)
    {
      digitalWrite(PB6, HIGH);
    }
    else
    {
      digitalWrite(PB6, LOW);
    }
  }
This will have the same phase for both pins, to shift the phase you need to be slightly more clever

stan
Posts: 44
Joined: Wed Nov 11, 2020 7:40 pm

Re: DMA problem

Post by stan »

Thanks
It is working, I activated this line and have 90 degree shift.

Code: Select all

  val1[i] = 40 + amp * cos(stp * i);

Post Reply

Return to “Projects”