2012-08-22 08:22 AM
Hi
The objective is to create avariable 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?2015-03-24 09:57 AM
Is there a reason to configure the timer as maximal, rather than at 5000, or 10000? At 5000 you'd keep getting an interrupt every 5ms and the counter would wrap automatically.
The purpose of HT/TC would be to keep a streaming DMA operation to be sustained.If there is adequate time between the 19th sample being loaded, and subsequently firing, you couple perhaps just service the TCWith a 38 sample buffer, HT/TC would fire at 19 sample intervals, allowing you to update the after-next portion of the table.How many of the 19 forward, vs 19 backward, sequences do you normally expect to send?2015-03-24 12:32 PM
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!!!
2015-03-24 12:41 PM
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?2015-03-24 12:48 PM
That is. Instead of reloading the table just move the pointer ...
DMA2_Strem1 -> ????? = (uint32_t) SRC_Buffer [0] [SPWM_ELEMENTS];2015-03-24 01:14 PM
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.2015-03-24 01:20 PM
233usg
So I thought it could be a good idea. Load the table before starting again.2015-03-24 01:28 PM
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 period2015-03-25 12:09 AM
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.2015-03-25 06:45 AM
Definitely after reading about double buffer I think is the solution. Could you tell me the steps to configure the program in this way?
2015-03-25 07:51 AM
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).