cancel
Showing results for 
Search instead for 
Did you mean: 

[HELP] STM32F4 generate PWM 3 channel shift phase 120 degree!

tranvanduy
Associate II
Posted on April 06, 2014 at 06:30

Hi all!

I want to control 3 phase motor (I get HDD motor from old HDD), and now I can generate 3 PWM signal on 3 channels but they are same, not

shift phase

120 degree!

Please help me!

I use STM32F4 discovery board and Keil!

Thanks all
40 REPLIES 40
hassanbhutta91
Associate II
Posted on September 22, 2014 at 11:14

hello  clive sir, i m doing the same thing but with stm32f303 vct6 , can you plz tell me the changing i have to do using f3, i m using tim1 ports PE9,PE11,PE13.

hassanbhutta91
Associate II
Posted on September 22, 2014 at 11:25

#include ''main.h''

int i=0, j=0;

GPIO_InitTypeDef bhutta;

void gpio();

void gpio()

     { 

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE,ENABLE );  

bhutta.GPIO_Mode=GPIO_Mode_AF;

     bhutta.GPIO_OType=GPIO_OType_PP;

        bhutta.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_11|GPIO_Pin_13;

      bhutta.GPIO_Speed=GPIO_Speed_50MHz;

         bhutta.GPIO_PuPd=GPIO_PuPd_NOPULL;

GPIO_Init(GPIOE,&bhutta);

GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_2);

GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_2);

GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_2);

 

}

 

TIM_TimeBaseInitTypeDef pwm_specification;

TIM_OCInitTypeDef oc;

int clk=72e6;

const int tim_freq =10000;

int prescaler=((72e6/tim_freq)-1);

const int pwm_freq=1;

const int pwm_period= tim_freq/pwm_freq;

//int ms=(float)pwm_period / (1000.0/pwm_freq); // for 200Hz we get: 10000 / (1/200 * 1000) = 2000

void timer_init()

{

 

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

pwm_specification.TIM_ClockDivision=0;

pwm_specification.TIM_CounterMode=TIM_CounterMode_Up;

pwm_specification.TIM_Period=pwm_period-1;

pwm_specification.TIM_Prescaler=prescaler-1;

//initilize channel

TIM_TimeBaseInit(TIM1,&pwm_specification);

oc.TIM_OCMode=TIM_OCMode_Toggle;

oc.TIM_OCPolarity=TIM_OCPolarity_High;

oc.TIM_OutputState=TIM_OutputState_Enable ;

oc.TIM_Pulse=(pwm_period/6);

TIM_OC1Init(TIM1, &oc);

oc.TIM_Pulse=(pwm_period/3)+(pwm_period/3);

TIM_OC2Init(TIM1, &oc);

oc.TIM_Pulse=(pwm_period/3)+(( pwm_period* 2) / 3);

TIM_OC3Init(TIM1, &oc);

TIM_Cmd(TIM1, ENABLE);

 

TIM_CtrlPWMOutputs(TIM1, ENABLE);

}

int main()

{

  gpio();

timer_init();

while(1)

{

TIM_SetCompare1(TIM1,1000);

TIM_SetCompare2(TIM1,1000);

TIM_SetCompare3(TIM1,1000);

}

}

#ifdef  USE_FULL_ASSERT

/**

  * @brief  Reports the name of the source file and the source line number

  *         where the assert_param error has occurred.

  * @param  file: pointer to the source file name

  * @param  line: assert_param error line source number

  * @retval None

  */

void assert_failed(uint8_t* file, uint32_t line)

  /* User can add his own implementation to report the file name and line number,

     ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */

  /* Infinite loop */

  while (1)

  {

  }

}

#endif

hassanbhutta91
Associate II
Posted on September 22, 2014 at 15:37

clive1 sir please tell me about the 120 degree phase shift in 3 pwm channels using TIM1 .i have posted my code , but there is no delay in pwm,s in oscilloscope.. plz find mistake in my code . thankue 

hassanbhutta91
Associate II
Posted on September 22, 2014 at 15:40

hye. clive sr .. please tell me about phase diff. 120 degree in 3 pwm channels of TIM1 of STM32F3

Posted on September 22, 2014 at 17:06

clive1 sir please tell me about the 120 degree phase shift in 3 pwm channels using TIM1 .i have posted my code , but there is no delay in pwm,s in oscilloscope.. plz find mistake in my code .

You set the compare points of all three channels to be the same (1000), and consequently all the edges will be placed at the same point, you have to infer the phase shift by placing the compare points at the points in the period rotation where you want the edges to fall.

Think of it like the dial on a clock, if you set everything at 10 o'clock that's when they all trigger. You'd want them at 1, 5 and 9 for example.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
hassanbhutta91
Associate II
Posted on September 22, 2014 at 17:49

yes . now phase shift has been added. sir can u plz tell me that how can i put dead time between these  3 channels and thier ciorresponding N (invert ) channels . (between channel and channelN and so for other 2 channels)

Posted on September 22, 2014 at 18:05

Yeah, I don't know why you didn't port the code as I presented it, it was pretty clean and portable. TIM1 you'd need to pay attention to the extra fields in the OC structure, and enable the PWM Output.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on September 22, 2014 at 18:33

yes . now phase shift has been added. sir can u plz tell me that how can i put dead time between these 3 channels and their corresponding N (invert ) channels . (between channel and channelN and so for other 2 channels)

That's really not my area, you'll need to review the documentation thoroughly to understand your options here. STM32F3-Discovery_FW_V1.0.0\Project\Peripheral_Examples\TIM_ComplementarySignals\main.c ?? This was my quick port to the STM32F3-Discovery board.

// STM32F3-Discovery TIM1 Triphase Output PE.9, PE.11 and PE.13 - sourcer32@gmail.com
#include ''stm32f30x.h''
//******************************************************************************
void RCC_Configuration(void)
{
/* enable peripheral clock for TIM1 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/* GPIOE clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);
}
//******************************************************************************
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOE Configuration: TIM1 on PE9/PE11/PE13 LED */
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_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* Connect TIM1 pin */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_2); // PE9 TIM1_CH1 LD3 RED
GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_2); // PE11 TIM1_CH2 LD7 GREEN
GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_2); // PE13 TIM1_CH3 LD10 RED
}
//******************************************************************************
void TIM1_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
int Prescaler, Period;
Prescaler = (SystemCoreClock / 360000); // 360 KHz timebase, assumes APB2 H/1 TIMCLK1 H/1
Period = 36000; // 10 Hz -> 5 Hz
// The toggle halves the frequency
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = Period - 1;
TIM_TimeBaseStructure.TIM_Prescaler = Prescaler - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Output Compare Toggle Mode configuration: Channel 1, 2 and 3 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
/* Default unused fields TIM1 more sensitive */
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
/* Don't want to set 0 or Period, but have 3 points at 120 degrees from each other */
TIM_OCInitStructure.TIM_Pulse = ((Period * 1) / 3) - 1;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = ((Period * 2) / 3) - 1;
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = ((Period * 3) / 3) - 1;
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
/* Enable pins, TIM1 more sensitive */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
/* TIM1 enable counter */
TIM_Cmd(TIM1, ENABLE);
}
//******************************************************************************
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
TIM1_Configuration();
while(1); /* Infinite loop */
}
/**************************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d

'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on September 22, 2014 at 18:52

Complementary

// STM32F3-Discovery TIM1 Triphase Output PE.9, PE.11 and PE.13 - sourcer32@gmail.com
// Plus complementary on PE.8, PE.10 and PE.12
#include ''stm32f30x.h''
//******************************************************************************
void RCC_Configuration(void)
{
/* enable peripheral clock for TIM1 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/* GPIOE clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);
}
//******************************************************************************
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOE Configuration: TIM1 on PE8/PE9/PE10/PE11/PE12/PE13 LED */
GPIO_InitStructure.GPIO_Pin =
GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* Connect TIM1 pin */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_2); // PE8 TIM1_CH1N LD4 BLUE
GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_2); // PE9 TIM1_CH1 LD3 RED
GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_2); // PE10 TIM1_CH2N LD5 ORANGE
GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_2); // PE11 TIM1_CH2 LD7 GREEN
GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_2); // PE12 TIM1_CH3N LD9 BLUE
GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_2); // PE13 TIM1_CH3 LD10 RED
}
//******************************************************************************
void TIM1_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
int Prescaler, Period;
Prescaler = (SystemCoreClock / 360000); // 360 KHz timebase, assumes APB2 H/1 TIMCLK1 H/1
Period = 36000; // 10 Hz -> 5 Hz
// The toggle halves the frequency
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = Period - 1;
TIM_TimeBaseStructure.TIM_Prescaler = Prescaler - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Output Compare Toggle Mode configuration: Channel 1, 2 and 3 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
/* Default unused fields TIM1 more sensitive */
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
/* Don't want to set 0 or Period, but have 3 points at 120 degrees from each other */
TIM_OCInitStructure.TIM_Pulse = ((Period * 1) / 3) - 1;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = ((Period * 2) / 3) - 1;
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
TIM_OCInitStructure.TIM_Pulse = ((Period * 3) / 3) - 1;
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
/* Enable pins, TIM1 more sensitive */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
/* TIM1 enable counter */
TIM_Cmd(TIM1, ENABLE);
}
//******************************************************************************
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
TIM1_Configuration();
while(1); /* Infinite loop */
}
/**************************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d

'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
hassanbhutta91
Associate II
Posted on October 17, 2014 at 20:58

hye clive sir.

how we can perform logic AND operation of PWM Channel 1 of TIM1 and pwm Channel 1 of TIM3 internally (using progmming)?