2020-07-27 02:44 AM
Hi all,
i am trying to generate a 3 phase sine wave with 120 degree phase shift by using stm32f030r8t6 nucleo board.
i can see the generated 3 phase sine wave on oscilloscope but the freq is not stable of the sine wave. it varies continuously from 40hz to 110 hz. please have a look on it and suggest me what can i do.
please find the attachment for code.
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++)
{
x=x+0.062832;
SinTable[i] = Start_Duty+(Duty_Diff*(sin(x)));
}
for(i=50;i<=74;i++)
{
x=x+0.062832;
SinTable[i] = Start_Duty+(Duty_Diff*(sin(x)));
}
for(i=75;i<=99;i++)
{
x=x+0.062832;
SinTable[i] = Start_Duty+(Duty_Diff*(sin(x)));
}
// 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();
}
Solved! Go to Solution.
2020-08-12 10:26 PM
In the ISR, check if TIMx_SR has the update flag set, and execute rest of ISR only if it has.
JW
2020-08-12 11:15 PM
@Community member
Ok i will try it.
With your help in the past my problems was solved on stm32f0, Thanks for this reply.
2020-08-13 02:01 AM
@Community member
I changed interrupt handler
void TIM1_BRK_UP_TRG_COM_IRQHandler(void)
{
ISR();
}
to
void TIM1_BRK_UP_TRG_COM_IRQHandler(void)
{
if((TIM1->SR & 0x0001) != 0)
{
ISR();
}
}
nothing changed in output sine wave and, sine wave freq still varying.
2020-08-15 06:03 AM
Sanju, There's two point in your code:
First, define variables that used in interrupt routines as volatile.
Second, for a 50 Hz sine wave with 100 samples, your sampling rate is 5000 Hz. and in your pictures your ISR frequency is very low. And in reality you should have 15 to 20 PWM pulse for each sample to have a stable PWM , if you have 16 pulse for each sample you need 5000 x 16 = 80,000 PWM frequency. For test you reduce Period to 599 so PWM frequency is 80,000 Hz. Adjust samples value by divide them by 2, and test again. also send us PWM signal picture too if possible.
2020-08-16 08:39 PM
@Msd.1
in my program whenever the ISR is called it toggles a pin PA5 (which is shown by green pulses in image) to debug the ISR calling freq.
So to be noted here that ISR toggles PA5 at each calling and update PWM duty cycle to form the sine wave.
to form a single pulse of sine wave there are 100 samples means ISR will be callled 100 times for one pulse of sine wave and PA5 will be toggled 100 times (100 times toggles makes 50 pulses).
so it means for every 50 pulses of PA5 (green color waveform) one pulse of sine wave will be generated.
if i notice from images there is two types of images (one for RCR=5 and Second one for RCR = 15)
CASE 1:
for RCR =5 freq is showing 3.32khz i.e. 3320hz.
so sine wave freq should be 3320/50 = 66.4hz
CASE 2:
for RCR =15 freq is showing 1.25khz i.e. 1250hz.
so sine wave freq should be 1250/50 = 25hz.
when this will be ok i will set program for different freq. my project is not to generate sine wave of 50hz it is to drive DC servo motor.
Note: PA5 is not in above program but it is in the conversation held already.
2020-09-11 02:45 AM
@Laurent Ca...
Can you have a look at this.