Hi all,
i am trying to generate 3 phase sine with 120degree phase shift by using STM32F030R8T6 MCU. i have its nucleo board Nucleo-F030R8
My code generates 3phase sine wave which i can see on CRO but the freq varies from 50 hz to 200 hz . freq is not stable.
please help me to figure out where i am doing wrong.
Here is the code which i have written
this is code of main.c file
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "stm32f0xx.h"
#include "stm32f030x8.h"
#include "math.h"
void GPIO_Init(void);
void EXTI_Init(void);
void TIM1_Init(void);
void TIM1I_Init(void);
void UpdatePulse(void);
unsigned int i,i1=0,i2=0,i3=0,count,Ch1_DutyCycle=0,Ch2_DutyCycle=0,Ch3_DutyCycle=0,Ch1_Dir=0,Ch2_Dir=0,Ch3_Dir=0,Max_Duty=0,Start_Duty=0,Duty_Diff=0,Period=0;
unsigned int SinTable[100],SineFreq=0;
double x=0;
int main()
{
/****start PLL setting for system clock at 48Mhz using 8Mhz HSI****/
RCC->CFGR |= ((1<<19)|(1<<21)); // PLL Multification factor = 12
RCC->CFGR |= (1<<1); // PLL selected as system clock
RCC->CR |= (1<<24); // Enable / ON PLL
while((RCC->CR & (1<<25)) == 0); // Wait until PLL gets Ready
/****PLL settigs end here****/
Period = 1199; // 40khz i.e. 20 khz in center aligned mode
Max_Duty = 1080; // 90%
Start_Duty = 600; // 50%
Duty_Diff = (Max_Duty-Start_Duty);
// Generating sine table , here x is angle
x=0;
for(i=0;i<=24;i++)
x=x+0.062832;
SinTable[i] = Start_Duty+(Duty_Diff*(sin(x)));
}
for(i=25;i<=49;i++)
for(i=50;i<=74;i++)
for(i=75;i<=99;i++)
// maintaining 120 deg phase shift between 3 sine waves.
i1 = 33; // 120 degree W
i2 = 66; // 240 degree V
i3 = 99; // 0/360 degree U
GPIO_Init(); // gpio initialization
TIM1_Init(); // timer1 initialization
TIM1I_Init(); // timer 1 interrupt initialization
while(1) // infinite loop
void GPIO_Init()
RCC->AHBENR |= (1<<17); // Enable clock for GPIOA
RCC->AHBENR |= (1<<18); // Enable clock for GPIOB
GPIOA->MODER |= (1<<17); // PA8 in alternate function mode TIM1_CH1
GPIOA->OTYPER &= ~(1<<8); // PA8 as output push pull
GPIOA->OSPEEDR |= ((1<<16)|(1<<17)); // PA8 at high speed
GPIOA->PUPDR &= ~((1<<16)|(1<<17)); // PA8 no pull-up, no pull-down
GPIOA->AFR[1] |= (1<<1); // PA8 as TIM1_CH1 alternate function
GPIOA->MODER |= (1<<19); // PA9 in alternate function mode TIM1_CH2
GPIOA->OTYPER &= ~(1<<9); // PA9 as output push pull
GPIOA->OSPEEDR |= ((1<<18)|(1<<19)); // PA9 at high speed
GPIOA->PUPDR &= ~((1<<18)|(1<<19)); // PA9 no pull-up, no pull-down
GPIOA->AFR[1] |= (1<<5); // PA9 as TIM1_CH1 alternate function
GPIOA->MODER |= (1<<21); // PA10 in alternate function mode TIM1_CH3
GPIOA->OTYPER &= ~(1<<10); // PA10 as output push pull
GPIOA->OSPEEDR |= ((1<<20)|(1<<21)); // PA10 at high speed
GPIOA->PUPDR &= ~((1<<20)|(1<<21)); // PA10 no pull-up, no pull-down
GPIOA->AFR[1] |= (1<<9); // PA10 as TIM1_CH1 alternate function
GPIOA->MODER |= (1<<15); // PA7 in alternate function mode TIM1_CH1N
GPIOA->OTYPER &= ~(1<<7); // PA7 as output push pull
GPIOA->OSPEEDR |= ((1<<14)|(1<<15)); // PA7 at high speed
GPIOA->PUPDR &= ~((1<<14)|(1<<15)); // PA7 no pull-up, no pull-down
GPIOA->AFR[0] |= (1<<29); // PA7 as TIM1_CH1 alternate function
GPIOB->MODER |= (1<<1); // PB0 in alternate function mode TIM1_CH2N
GPIOB->OTYPER &= ~(1<<0); // PB0 as output push pull
GPIOB->OSPEEDR |= ((1<<0)|(1<<1)); // PB0 at high speed
GPIOB->PUPDR &= ~((1<<0)|(1<<1)); // PB0 no pull-up, no pull-down
GPIOB->AFR[0] |= (1<<1); // PB0 as TIM1_CH1 alternate function
GPIOB->MODER |= (1<<3); // PB1 in alternate function mode TIM1_CH3N
GPIOB->OTYPER &= ~(1<<1); // PB1 as output push pull
GPIOB->OSPEEDR |= ((1<<2)|(1<<3)); // PB1 at high speed
GPIOB->PUPDR &= ~((1<<2)|(1<<3)); // PB1 no pull-up, no pull-down
GPIOB->AFR[0] |= (1<<5); // PB1 as TIM1_CH1 alternate function
void TIM1_Init()
RCC->APB2ENR |= (1<<11); // Enable clock for TIM1
TIM1->PSC = 0;
TIM1->ARR = Period; // period
TIM1->CR1 |= ((1<<5)); // Center-aligned mode 1.
TIM1->CR1 |= ((1<<2)); // Only counter overflow/underflow generates an update interrupt
TIM1->DIER = 1; // Update interrupt enable
TIM1->RCR = 5; // update event after RCR+1 period
TIM1->CCMR1 |= ((1<<4)|(1<<5)|(1<<6)|(1<<3)); // TIM1_CH1 is set to pwm mode-2
TIM1->CCMR1 |= ((1<<12)|(1<<13)|(1<<14)|(1<<11)); // TIM1_CH2 is set to pwm mode-2
TIM1->CCMR2 |= ((1<<4)|(1<<5)|(1<<6)|(1<<3)); // TIM1_CH3 is set to pwm mode-2
Ch1_DutyCycle = SinTable[i1]; // 120 degree W @ start
Ch2_DutyCycle = SinTable[i2]; // 240 degree V @ start
Ch3_DutyCycle = SinTable[i3]; // 0/360 degree U @ start
TIM1->CCR1 = Ch1_DutyCycle; // Ch1 duty cycle
TIM1->CCR2 = Ch2_DutyCycle; // Ch2 duty cycle
TIM1->CCR3 = Ch3_DutyCycle; // Ch3 duty cycle
TIM1->CCER |= ((1<<0)|(1<<2)); // TIM1_CH1, TIM1_CH1N is Active, active high
TIM1->CCER |= ((1<<4)|(1<<6)); // TIM1_CH2, TIM1_CH2N is Active, active high
TIM1->CCER |= ((1<<8)|(1<<10)); // TIM1_CH3, TIM1_CH3N is Active, active high
TIM1->BDTR |= (1<<15); // main output enable
TIM1->BDTR |= (1<<14); // automatic output enable
TIM1->BDTR |= ((1<<5)|(1<<4)|(1<<3)); // dead time
TIM1->EGR = 1; // Reinitialize the counter and generates an update of the registers
TIM1->CR1 |= 1; // TIM1 Counter enable
void TIM1I_Init()
// interrupt enabling settings
__NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 0);
__NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn);
void ISR()
UpdatePulse();
TIM1->SR = 0; // clear update interrupt flag
void UpdatePulse()
i1++;
if(i1>99)
i1=0;
Ch1_DutyCycle = SinTable[i1];
i2++;
if(i2>99)
i2=0;
Ch2_DutyCycle = SinTable[i2];
i3++;
if(i3>99)
i3=0;
Ch3_DutyCycle = SinTable[i3];
TIM1->CCR1 = Ch1_DutyCycle; // duty cycle
TIM1->CCR2 = Ch2_DutyCycle; // duty cycle
TIM1->CCR3 = Ch3_DutyCycle; // duty cycle
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// this is code of it.c file
void ISR(void);
void TIM1_BRK_UP_TRG_COM_IRQHandler(void)
ISR();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Clive Unspecified
Try to use HSE as sys clock source.
Hi sanjay kumawat
Just for your information I have moved your thread to the Cortex-M forum where it should live.
Thanks!