cancel
Showing results for 
Search instead for 
Did you mean: 

Variable frequency pulse train for pulse transformer application

arre24
Associate II
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?
53 REPLIES 53
Posted on March 13, 2014 at 03:42

if u are familiar with working of USART, can u help me?

If you want help with USART code, please start a new thread, and state the issue
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sanjib
Associate III
Posted on March 24, 2014 at 06:28

Dear Joseph,

Sorry for late reply as my board got spoiled so I am busy to make it up  . Yes I am familiar with USART and I can help you .
indermohan
Associate
Posted on August 29, 2014 at 03:59

Is it necessary to you DMA for capture compare .

I am using timer1 channel 1 as output compare, to generate a pulse of variable period.

The output mode is set to toggle mode and the polarity is set to active high. T

he capture register is set to delay period and then in next capture register set to first period and next period will be updated after the one pulse is completed.

0690X00000602wpQAA.jpg

I is correct expected output. II is wrong in this case the wrong ramp profile and driver consider wrong first step .As driver  considers first rising edge as first step  

Posted on August 29, 2014 at 04:20

The use of DMA would depend on what frequency you want to generate and how practical it is to interrupt.

With toggle mode you get to control where the edge transitions are placed with respect to the time base of the counter, if you want a longer lead in, then push out the edge further.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
arre24
Associate II
Posted on September 08, 2014 at 18:29

I would recommend having a table in RAM containing the time stamps of the rising/falling flanks. The let the DMA transfer these values to the timer compare register using memory increment mode. The timer output pin should be configured to toggle at every compare match.

webmaster
Associate II
Posted on March 17, 2015 at 09:13

Hello Clif

Thanks for you job, has been the better help for my. In the using this code, I  had  a  problem. I need recharge a table with values. These values range from 0 degrees to 90 degrees  . The following interruption values are 90 to 180 are loaded and so on. . I do not work.

If I leave the same table if the recharge bienpero if no alternative. Each table has 19 values ranging from 0-5000 us and complete the following period until the 10000 usg.

I need help thanks in advance

Vincent Onde
ST Employee
Posted on March 17, 2015 at 10:22

Hello,

Just a remark, as I noticed this thread is still active.

There is now a STM32 (the STM32F334) with a built-in chopper mode for PWM, in the High-Resolution Timer (HRTIM).

Best regards,

Vincent

Posted on March 17, 2015 at 15:40

Hello Clif

 

Thanks for you job, has been the better help for my. In the using this code, I  had  a  problem. I need recharge a table with values. These values range from 0 degrees to 90 degrees  . The following interruption values are 90 to 180 are loaded and so on. . I do not work. If I leave the same table if the recharge bienpero if no alternative. Each table has 19 values ranging from 0-5000 us and complete the following period until the 10000 usg.

 

I need help thanks in advance

Clive!

You'll need to modify the length of the DMA transfer to the portion of the phase you want to supply data for. You can also use the HT (Half Transfer) and TC (Terminal Count) interrupts of the DMA to split the buffer in half and allow you to build the next table of data while the current one is being dispatched.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
webmaster
Associate II
Posted on March 18, 2015 at 12:54

Sorry Clive,

The spellchecker playing tricks on me. It's the price you pay for not knowing English well. The DMA is well sized and interrupt each half. From serious table ideal, I do not know how. Could you give me an example. Anyway you step the code that I modified.

uint16_t SRC_Buffer [SPWM_ELEMENTS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

uint16_t Tabla_Buffer [5][DISPAROS] = {
{270 , 319 , 539 , 591 , 829 , 898 , 1159 , 1239 , 1504 , 1593 , 1855 , 1951 , 2210 , 2310 , 2565 , 2669 , 2922 , 3028 , 3280 }, // K = 0.3
{251 , 316 , 523 , 594 , 816 , 908 , 1145 , 1252 , 1488 , 1607 , 1838 , 1965 , 2192 , 2325 , 2547 , 2685 , 2904 , 3045 , 3262 }, // K = 0.4
{233 , 314 , 508 , 599 , 803 , 918 , 1130 , 1264 , 1472 , 1620 , 1821 , 1980 , 2174 , 2341 , 2529 , 2702 , 2886 , 3062 , 3244 }, // K = 0.5
{216 , 314 , 495 , 606 , 791 , 929 , 1116 , 1276 , 1456 , 1633 , 1803 , 1993 , 2155 , 2355 , 2510 , 2718 , 2867 , 3079 , 3226 }, // K = 0.6
{199 , 314 , 481 , 613 , 779 , 940 , 1102 , 1287 , 1439 , 1645 , 1784 , 2006 , 2135 , 2369 , 2489 , 2733 , 2847 , 3096 , 3208 } // K = 0.7
};
void TIM1_CC_IRQHandler(void)
{ 
static bool semiciclo;
/* check if the TIM1_CC4 interrupt has occurred */
if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET)
{
/* clear the TIM1_CC4 interrupt pending bits */
TIM_ClearITPendingBit(TIM1, TIM_IT_CC4);
}
TIM1->CNT = 0; /* Reset the counter back to zero */
/* Set up data for DMA-transfer */
semiciclo = !semiciclo;
if (semiciclo) 
{
TIM1->CCR1 = SRC_Buffer[0] = Tabla_Buffer [Tabla][0];
SRC_Buffer[1] = Tabla_Buffer [Tabla][1];
SRC_Buffer[2] = Tabla_Buffer [Tabla][2];
SRC_Buffer[3] = Tabla_Buffer [Tabla][3];
SRC_Buffer[4] = Tabla_Buffer [Tabla][4];
SRC_Buffer[5] = Tabla_Buffer [Tabla][5];
SRC_Buffer[6] = Tabla_Buffer [Tabla][6];
SRC_Buffer[7] = Tabla_Buffer [Tabla][7];
SRC_Buffer[8] = Tabla_Buffer [Tabla][8];
SRC_Buffer[9] = Tabla_Buffer [Tabla][9];
SRC_Buffer[10] = Tabla_Buffer [Tabla][10];
SRC_Buffer[11] = Tabla_Buffer [Tabla][11];
SRC_Buffer[12] = Tabla_Buffer [Tabla][12];
SRC_Buffer[13] = Tabla_Buffer [Tabla][13];
SRC_Buffer[14] = Tabla_Buffer [Tabla][14];
SRC_Buffer[15] = Tabla_Buffer [Tabla][15];
SRC_Buffer[16] = Tabla_Buffer [Tabla][16];
SRC_Buffer[17] = Tabla_Buffer [Tabla][17];
SRC_Buffer[18] = Tabla_Buffer [Tabla][18]; //(5000 + (5000 - Tabla_Buffer [Tabla][18]));/*Pulso central entre 60º y 120º */;
GPIO_WriteBit(GPIOE,GPIO_Pin_9,Bit_SET);
}
else
{ 
TIM1->CCR1 = SRC_Buffer[0] = (5000 - Tabla_Buffer [Tabla][18]);
SRC_Buffer[1] = (5000 - Tabla_Buffer [Tabla][17]);
SRC_Buffer[2] = (5000 - Tabla_Buffer [Tabla][16]);
SRC_Buffer[3] = (5000 - Tabla_Buffer [Tabla][15]);
SRC_Buffer[4] = (5000 - Tabla_Buffer [Tabla][14]);
SRC_Buffer[5] = (5000 - Tabla_Buffer [Tabla][13]);
SRC_Buffer[6] = (5000 - Tabla_Buffer [Tabla][12]);
SRC_Buffer[7] = (5000 - Tabla_Buffer [Tabla][11]);
SRC_Buffer[8] = (5000 - Tabla_Buffer [Tabla][10]);
SRC_Buffer[9] = (5000 - Tabla_Buffer [Tabla][9]);
SRC_Buffer[10] = (5000 - Tabla_Buffer [Tabla][8]);
SRC_Buffer[11] = (5000 - Tabla_Buffer [Tabla][7]);
SRC_Buffer[12] = (5000 - Tabla_Buffer [Tabla][6]);
SRC_Buffer[13] = (5000 - Tabla_Buffer [Tabla][5]);
SRC_Buffer[14] = (5000 - Tabla_Buffer [Tabla][4]);
SRC_Buffer[15] = (5000 - Tabla_Buffer [Tabla][3]);
SRC_Buffer[16] = (5000 - Tabla_Buffer [Tabla][2]);
SRC_Buffer[17] = (5000 - Tabla_Buffer [Tabla][1]);
SRC_Buffer[18] = (5000 - Tabla_Buffer [Tabla][0]);
GPIO_WriteBit(GPIOE,GPIO_Pin_9,Bit_RESET);
}
/* Next interrupt to occur after 5 ms */
TIM1->CCR4 = 5000;
}

Need guidance on HT (Half Transfer) and TC (Terminal Count) may be the solution. Very grateful for your prompt reply. I hope your coments.

DMA_InitStructure.DMA_Channel = DMA_Channel_6;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(TIM1_CCR1_ADDRESS);
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)SRC_Buffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = SPWM_ELEMENTS; // Nº data items to transfer
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream1, &DMA_InitStructure);
DMA_Cmd(DMA2_Stream1, ENABLE); // enable DMA2_Stream1

webmaster
Associate II
Posted on March 21, 2015 at 21:41

Hi Clive1

I found Looking for

DMA_ITConfig (DMAx_Channelx, DMA_IT_TC | DMA_IT_HT | DMA_IT_TE, DISABLE);

I guess you meant this. I do not see how to use it for my program.