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-21 05:16 PM
Not sure I've got enough context here to see exactly what you're doing. I don't understand how the CCR4 5ms things is going to work.
You have 19 CCR1 values which I assume get loaded at each Update interval. You can get the DMA channel to interrupt either when it completes sending a buffer, or does half a one. You can get the TIM to interrupt on each Update, but this might be too rapid. You could create a DMA buffer length, or half length, such that it interrupts every 5 ms, at which point you could update portions of the table. I don't know how many samples that will be in this context. Perhaps you can present a complete example?2015-03-22 02:00 AM
I need to load the table with alpha values from 0 degrees to 90 degrees. Before the end you should be loading from 90 to 180. You can not split the tablets because the values are odd and I need that high or low levels remain inthe table changes. These levels SRC_Buffer maintains only [0].
notice that the values in Table 90 to 180 are a mirror table 90. TIM1- 0> CCR1 = SRC_Buffer [0] = (5000 - Tabla_Buffer [Table] [18]);2015-03-22 02:02 AM
2015-03-22 02:18 AM
Clive Sorry,I forgot.
The regulation requires the refreshment table at 90 degrees or what is the same five msg2015-03-22 08:46 AM
So, I'm assuming 5ms (200Hz). I'm not convinced you need to build the entire table, you could build 20 entries initially (0..19), at HT (10 entries) you could rebuild/replace the first 10 (20..29), at TC the next 10 (30..39), etc.
Or you could do 5 at a time, and not stuff the CCR1 value, or CNT2015-03-22 08:53 AM
I'm missing the frequency/period details, the relationship of the 5 milliseconds, 5 messages, 19/38 samples, why the entire sequence can't be in a single table, or built on the fly.
2015-03-22 02:20 PM
The frequency is 100Hz. The table has 19 values, ranging from 0 degrees to 90 degrees. The values from 90-100 degrees to complete the cycle are constructed by the mirror table from 0 degrees to 90 degrees.
I have tried using CT and HT and malfunctions. DMA2_Stream1_IRQHandler not interrupt me and has stopped working USART3. As you can see I tried to load half the table and segundamitad 0-9 9-18, but not if it works as there is no interruption for loading them. The tables are pre-calculated and stored are an 500 have 19 values eachvoid DMA2_Stream1_IRQHandler(void)
{
if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF2))
{
// Transfer complete.
DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF2);
if (semiciclo)
{
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];
}
else
{
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]);
}
}
else if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_HTIF2))
{
// Half transfer.
DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_HTIF2);
if (semiciclo)
{
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]);
}
else
{
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];
}
}
else if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_TEIF2))
{
// Transfer error.
DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TEIF2);
}
}
2015-03-22 02:23 PM
void TIM1_CC_IRQHandler(void)
{
/* 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)
{
GPIO_WriteBit(GPIOE,GPIO_Pin_9,Bit_SET);
}
else
{
GPIO_WriteBit(GPIOE,GPIO_Pin_9,Bit_RESET);
}
/* Next interrupt to occur after 5 ms */
TIM1->CCR4 = 5000;
}
void NVIC_Configuration(void)
{
// When the compare event CC4 on TIM1 occurs, this interrupt begins to execute
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM1_CC_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
/* Enable the USARTx Interrupt */
NVIC_InitStruct.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
/* Enable the UARTx Interrupt */
NVIC_InitStruct.NVIC_IRQChannel = UART4_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
/* Enable the DMA2_Stream1 Interrupt */
NVIC_InitStruct.NVIC_IRQChannel = DMA2_Stream1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
// TIM4_UP - DMA1, Channel 2, Stream 6
DMA_InitStructure.DMA_Channel = DMA_Channel_2;
DMA_InitStructure.DMA_BufferSize = PWM_ELEMENTS;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&PWM_Buffer[0];
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM4->CCR1;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_Init(DMA1_Stream6, &DMA_InitStructure);
DMA_Cmd(DMA1_Stream6, ENABLE);// turning DMA on
// TIM1 - DMA2, Channel 6, Stream 1
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);
// Enable Transfer Complete, Half Transfer and Transfer Error interrupts.
DMA_ITConfig(DMA2_Stream1, DMA_IT_TC | DMA_IT_HT | DMA_IT_TE, ENABLE);
DMA_Cmd(DMA2_Stream1, ENABLE); // enable DMA2_Stream1
// wait until the DMA stream is enabled
while (DMA_GetCmdStatus(DMA2_Stream1) != ENABLE)
{
}
}
2015-03-22 03:01 PM
DMA_IT_TCIF2 << This should be TCIF1 for Stream1
How is the timer configured? It's very hard to figure out what's going to happen with random assortments of code, please post a complete/concise example, without line numbers.2015-03-23 01:55 PM