Page 2 of 3

Re: DMA problem

Posted: Fri Nov 20, 2020 5:58 pm
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() {
}
 

Re: DMA problem

Posted: Fri Nov 20, 2020 6:04 pm
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.

Re: DMA problem

Posted: Fri Nov 20, 2020 10:53 pm
by stevestrong
If you want to use DMA, then try the last alternative method as suggested in my previous post.

Re: DMA problem

Posted: Sat Nov 21, 2020 8:02 am
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

Re: DMA problem

Posted: Sat Nov 21, 2020 10:31 am
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 ?

Re: DMA problem

Posted: Sat Nov 21, 2020 11:42 am
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.

Re: DMA problem

Posted: Sat Nov 21, 2020 1:21 pm
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);
    }

}

Re: DMA problem - solved

Posted: Sat Nov 21, 2020 2:40 pm
by stan
Can't get 50% pulses simultaneously on PB6 and PB8, separately pulses are ok 50%

Re: DMA problem

Posted: Sat Nov 21, 2020 4:17 pm
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

Re: DMA problem

Posted: Sat Nov 21, 2020 4:53 pm
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);