AnsweredAssumed Answered

DMA triggerted by TIMx that copy data to CCR of TIMy

Question asked by karpavicius.linas on Dec 4, 2015
Latest reply on Dec 4, 2015 by karpavicius.linas
Hello, i need to implement hardware triggering by TIM8 ( as example) that will copy PWM table to TIM1->CCR1,2,3

Idea is, i want to turn 3phase motor with 3P_PWM +3N_PWM outputs
(3H bride so 6lines of PWM) , and speed should be controlled by other timer period, since it will copy coeficcients to first timer CCR register

I was able to make example work, but i can't only way to change frequency is to change prescaller.

Or in other words, i simply need to get more resolution for my motor to spin, because if i run at 400Hz, that means i need around 7 times larger period in CCR register ( due to poles)  and jumps between RPM at high speed is too big, motor start to shake. At low speed i have good RPM resolution to not feel any effect
I have 256 phase steps in single sinus period.

Or maybe some one can tell me, how to get more motor speed resolution at 400Hz (pwm must run 7 times faster CCR period)

Here is my code:
#include "stm32f4xx.h"
#include "math.h"
 
void DMA_Config(void);
void TIM_Config(void);
uint32_t index =0;
void Delay(uint32_t a)
{
  while(a)
  {
    a--;
    asm("nop");
  }
}
 
uint16_t Phase_A[256];
uint16_t Phase_B[256];
uint16_t Phase_C[256];
 
 
 
int main(void)  
{
  Delay(0xFFFF);
  uint32_t i=0;
  while(i<256)
  {
    Phase_A[i]=(uint16_t)(128.0f*(1+sinf((6.2831853f*i/256.0f))));
    Phase_B[i]=(uint16_t)(128.0f*(1+sinf(((6.2831853f*i)/256.0f)+2.0943f)));
    Phase_C[i]=(uint16_t)(128.0f*(1+sinf(((6.2831853f*i)/256.0f)+4.1887f)));
    i++;
  }
  TIM_Config();
  DMA_Config();
 
  DMA_ITConfig(DMA2_Stream1, DMA_IT_TC, ENABLE) ;
   
  TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
  TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
  TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
   
  /* TIM1 counter enable */
  TIM_Cmd(TIM1, ENABLE);
  DMA_Cmd(DMA2_Stream1, ENABLE);
  DMA_Cmd(DMA2_Stream2, ENABLE);
  DMA_Cmd(DMA2_Stream6, ENABLE);
  while(1);
}
 
void DMA_Config(void)
{
  DMA_InitTypeDef DMA_InitStructure;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 , ENABLE);
 
  DMA_DeInit(DMA2_Stream6);
  DMA_DeInit(DMA2_Stream2);
  DMA_DeInit(DMA2_Stream1);
 
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStructure.DMA_BufferSize = 256;
  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_PeripheralDataSize_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_InitStructure.DMA_Channel = DMA_Channel_6
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM1->CCR3;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Phase_C;
  DMA_Init(DMA2_Stream6, &DMA_InitStructure);
    
  DMA_InitStructure.DMA_Channel = DMA_Channel_6; 
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM1->CCR2 ;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Phase_B;
  DMA_Init(DMA2_Stream2, &DMA_InitStructure);
   
  DMA_InitStructure.DMA_Channel = DMA_Channel_6; 
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM1->CCR1 ;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Phase_A;
  DMA_Init(DMA2_Stream1, &DMA_InitStructure);
  
  TIM_DMACmd(TIM1, TIM_DMA_CC1, ENABLE);
  TIM_DMACmd(TIM1, TIM_DMA_CC2, ENABLE);
  TIM_DMACmd(TIM1, TIM_DMA_CC3, ENABLE);
}
 
 
void TIM_Config(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
   
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
   
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
   
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
   
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
   
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_TIM1);
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_TIM1);
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_TIM1);
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_TIM1);
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_TIM1);
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_TIM1);
   
 
  TIM_TimeBaseStructure.TIM_Prescaler = 3;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_Period = 255;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
 
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 0;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
 
  TIM_OC1Init(TIM1, &TIM_OCInitStructure);
  TIM_OCInitStructure.TIM_Pulse = 0;
   
  TIM_OC2Init(TIM1, &TIM_OCInitStructure);
 
  TIM_OCInitStructure.TIM_Pulse = 0;
  TIM_OC3Init(TIM1, &TIM_OCInitStructure);
  TIM1->BDTR|=30;
   
  TIM_ARRPreloadConfig(TIM1, ENABLE);
  TIM_CtrlPWMOutputs(TIM1, ENABLE);
  TIM_Cmd(TIM1, ENABLE);
}


Outcomes