Skip to main content
arre24
Associate
August 22, 2012
Question

Variable frequency pulse train for pulse transformer application

  • August 22, 2012
  • 53 replies
  • 8009 views
Posted on August 22, 2012 at 17:22

Hi

The objective is to create a

variable frequency

pulse train with as little CPU intervention as possible.

This was quite straightforward with the TMS320 TI MCU. It had a feature called ''PWM chopper'' where it was possible to configure frequency, pulse width, duty cycle and number of pulses.

To achieve the same kind of functionality with the STM32F4, the idea that first came to mind was to use the Advanced Control Timer & DMA peripheral.

A table which consists of the timer periods that define the pulse train characteristics is setup in RAM. The have the DMA transfer these values to the timer compare register using memory increment mode. The timer output pin is configured to toggle at every compare match. 

Also, it is desired to have control of the time interval between each consecutive pulse train. Therefore a timer capture/compare interrupt is enabled. In the interrupt, the pulse train starting time (first positive flank) is defined as:

Current time (time when the interrupt occurs) + A settable delay

The time when the next interrupt occurs is also settable.

The questions are:

1) Is the method described above possible with the STM32F4?

2) Are there any other ways to get the same result?
    This topic has been closed for replies.

    53 replies

    webmaster
    Visitor II
    March 24, 2015
    Posted on March 24, 2015 at 20:32

    I've also tried this.

    void DMA2_Stream1_IRQHandler(void)
    {
    if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF1))
    {
    // Transfer complete.
    DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1);
    if (semiciclo)
    {
    TIM1->CCR1 = SRC_Buffer[0] = 233;//Tabla_Buffer [0];
    SRC_Buffer[1] Tabla_Buffer [1];
    SRC_Buffer[2] Tabla_Buffer [2];
    SRC_Buffer[3] Tabla_Buffer [3];
    SRC_Buffer[4] Tabla_Buffer [4];
    SRC_Buffer[5] Tabla_Buffer [5];
    SRC_Buffer[6] Tabla_Buffer [6];
    SRC_Buffer[7] Tabla_Buffer [7];
    SRC_Buffer[8] Tabla_Buffer [8];
    SRC_Buffer[9] Tabla_Buffer [9];
    SRC_Buffer[10] Tabla_Buffer [10];
    SRC_Buffer[11] Tabla_Buffer [11];
    SRC_Buffer[12] Tabla_Buffer [12];
    SRC_Buffer[13] Tabla_Buffer [13];
    SRC_Buffer[14] Tabla_Buffer [14];
    SRC_Buffer[15] Tabla_Buffer [15];
    SRC_Buffer[16] Tabla_Buffer [16];
    SRC_Buffer[17] Tabla_Buffer [17];
    SRC_Buffer[18] Tabla_Buffer [18];
    }
    else
    {
    TIM1->CCR1 = SRC_Buffer[0] = 1756;//(5000 - Tabla_Buffer [18]);
    SRC_Buffer[1] (5000 - Tabla_Buffer [17]);
    SRC_Buffer[2] (5000 - Tabla_Buffer [16]);
    SRC_Buffer[3] (5000 - Tabla_Buffer [15]);
    SRC_Buffer[4] (5000 - Tabla_Buffer [14]);
    SRC_Buffer[5] (5000 - Tabla_Buffer [13]);
    SRC_Buffer[6] (5000 - Tabla_Buffer [12]);
    SRC_Buffer[7] (5000 - Tabla_Buffer [11]);
    SRC_Buffer[8] (5000 - Tabla_Buffer [10]);
    SRC_Buffer[9] (5000 - Tabla_Buffer [9]);
    SRC_Buffer[10] (5000 - Tabla_Buffer [8]);
    SRC_Buffer[11] (5000 - Tabla_Buffer [7]);
    SRC_Buffer[12] (5000 - Tabla_Buffer [6]);
    SRC_Buffer[13] (5000 - Tabla_Buffer [5]);
    SRC_Buffer[14] (5000 - Tabla_Buffer [4]);
    SRC_Buffer[15] (5000 - Tabla_Buffer [3]);
    SRC_Buffer[16] (5000 - Tabla_Buffer [2]);
    SRC_Buffer[17] (5000 - Tabla_Buffer [1]);
    SRC_Buffer[18] (5000 - Tabla_Buffer [0]);
    }
    }
    else if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_HTIF1))
    {
    // Half transfer.
    DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_HTIF1);
    }
    else if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_TEIF1))
    {
    // Transfer error.
    DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TEIF1);
    }
    }

    and does not work!!!
    webmaster
    Visitor II
    March 24, 2015
    Posted on March 24, 2015 at 20:41

    I need to recharge every 5000msg because I have to update the table. In the example there is only one but really are 500 tables.

    You can change each TC table on DMA? How?

    webmaster
    Visitor II
    March 24, 2015
    Posted on March 24, 2015 at 20:48

    That is. Instead of reloading the table just move the pointer ...

    DMA2_Strem1 -> ????? = (uint32_t) SRC_Buffer [0] [SPWM_ELEMENTS];

    Tesla DeLorean
    Guru
    March 24, 2015
    Posted on March 24, 2015 at 21:14

    I believe you'd have to stop the DMA to change the address, you could also look at the double buffering options.

    What's the minimum time delta between the last sample and the 5ms window?

    I don't think setting the TIMx->CCRx is a good plan in the TC interrupt, the timer may not have gotten to 5ms at that point. It's the point where it's delivered the last sample, but the compare point may not have been hit yet either.
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    webmaster
    Visitor II
    March 24, 2015
    Posted on March 24, 2015 at 21:20

    233usg

    So I thought it could be a good idea. Load the table before starting again.

    Tesla DeLorean
    Guru
    March 24, 2015
    Posted on March 24, 2015 at 21:28

    I think you can get the first sample into the table in that time.

    Sample point 18 hits on the timer, sample 19 loads into the compare register. TC fires. Load the first 16 samples for the next period (5ms / 5000 of the timer), when HT fires load samples 17, 18, 19 for the now current period

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    webmaster
    Visitor II
    March 25, 2015
    Posted on March 25, 2015 at 08:09

    I really need something more robust. Sometime I would  put more shots on the table and would return to having to touch this code. I thought this would have more defined micro utilities for these tasks.

    Posivilidad you were saying the double buffer options. Would this be a more robust and configurable way for this problem?

    I sincerely appreciate the help that they provide me.

    webmaster
    Visitor II
    March 25, 2015
    Posted on March 25, 2015 at 14:45

    Definitely after reading about double buffer I think is the solution. Could you tell me the steps to configure the program in this way?

    Tesla DeLorean
    Guru
    March 25, 2015
    Posted on March 25, 2015 at 15:51

    I don't have any examples for the case. You'll need to review the docs and the library source.

    I'm not sure how the method is less robust than the ones you've already presented, it uses less interrupts, and doesn't meddle with the timer phase or compares. You could make the pattern buffer much bigger, and the wrap of the counter much longer (multiples of 5ms, or whatever).

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    webmaster
    Visitor II
    March 26, 2015
    Posted on March 26, 2015 at 07:46

    No works well .. Maybe I did not understand the steps.

    It is a commentary on the double buffer based on a RAPID reading. I have not implemntado. I seemed at first code more flexible to change.