2015-02-06 08:29 AM
Can someone explain why the following code causes CCR1, CCR2 and CCR3 to have the same value:
TIM1->CCR1=value1; TIM1->CCR2=value2; TIM1->CCR3=value3; While the following code doesn't cause this problem (CCR1 and CCR2 different values): TIM1->CCR1=value1; TIM1->CCR2=value2;2015-02-06 08:41 AM
Let me guess: value1, value2 and value3 in the first instance are uninitialized local variables?
JW2015-02-06 08:53 AM
Preloaded or Immediate?
Post some actual code that demonstrates your issue.2015-02-06 09:12 AM
If I comment lineTIM1->CCR3=val2;, the channels 1 and 2 work properly.If not commented, the three output waves will have the same duty cycle(varying sinusoidaly of course). void
TIM1_CC_IRQHandler( void ) { int val; // integer values, because counter is not double int val1; int val2; double inbtw; // double values, used for calculations with sine wave double inbtw1; double inbtw2; cx++; // Refresh counter if (cx>1799) //If reached maximum then reset { cx=1; } if (parameter==1) //If direct phase sequence { inbtw=scalefactor*sin(2*3.1416*freqfactor*( double )cx/1799); // Calculate value of sinus wave val=( int )((inbtw*1799)/2+1799/2); // Shift value (only positive values are accepted) and convert to int //same for other phases inbtw1=scalefactor*sin(2*3.1416*freqfactor*(( double )cx/1799+2/3*3.1416)); val1=( int )((inbtw1*1799)/2+1799/2); // note +120 and -120phase shift inbtw2=scalefactor*sin((2*3.1416*freqfactor*( double )cx/1799)-2/3*3.1416); val2=( int )((inbtw2*1799)/2+1799/2); } if (parameter==2) // If indirect phase sequence { inbtw=scalefactor*sin(2*3.1416*freqfactor*( double )cx/1799); val=( int )((inbtw*1799)/2+1799/2); inbtw1=scalefactor*sin(2*3.1416*freqfactor*( double )cx/1799-2/3*3.1416); val1=( int )((inbtw1*1799)/2+1799/2); inbtw2=scalefactor*sin(2*3.1416*freqfactor*( double )cx/1799+2/3*3.1416); val2=( int )((inbtw2*1799)/2+1799/2); } if (val<1) { val=1; } if (val1<1) { val1=1; } if (val2<1) { val2=1; } TIM1->CCR1=val; TIM1->CCR2=val1; TIM1->CCR3=val2; // IRQ handling HAL_NVIC_ClearPendingIRQ(TIM1_CC_IRQn); //reset pending flag HAL_TIM_IRQHandler(&htim1); //continue }2015-02-06 09:13 AM
/* TIM1 init function */
void
MX_TIM1_Init(
void
)
{
TIM_OC_InitTypeDef sConfigOC;
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim1.Instance = TIM1;
htim1.Init.Prescaler = (uint32_t) (SystemCoreClock / 18000000) - 1;
htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1;
htim1.Init.Period = 1799;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
HAL_TIM_PWM_Init(&htim1);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 450;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_SET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_SET;
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2);
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3);
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_1;
sBreakDeadTimeConfig.DeadTime = 255;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_ENABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE;
HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);
if
(HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/* Start channel 1 */
if
(HAL_TIM_PWM_Start_IT(&htim1, TIM_CHANNEL_1) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
/* Start channel 1N */
if
(HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
/* Start channel 2 */
if
(HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
/* Start channel 2N */
if
(HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
/* Start channel 3 */
if
(HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
/* Start channel 3N */
if
(HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3) != HAL_OK)
{
/* Starting Error */
Error_Handler();
}
}
2015-02-06 10:39 AM
I don't understand how could it lead to described symptoms, but you are attempting some very heavy math (double is calculated entirely in software), which might in case of 3 channels lead to ISR taking longer than the reload period.
JW2015-02-06 11:48 AM
inbtw1=scalefactor*sin(2*3.1416*freqfactor*((
double
)cx/1799+2/3*3.1416));
inbtw2=scalefactor*sin((2*3.1416*freqfactor*(
double
)cx/1799)-2/3*3.1416);
Review your brackets
2015-02-06 12:00 PM
Thanks for the suggestions, I'll try and post results after.
2015-02-06 12:14 PM
I'm not 100% convinced on the math here as it relates to the scalefactor, and inbtw, but this looks to be doable with float, and not doubles.
void TIM1_CC_IRQHandler(void)
{
const float pi2ff = 2.0f * 3.141592f * (float)freqfactor;
const float phase120 = 2.0f / 3.0f * 3.141592f;
const float recip1799 = 1.0f / 170f;
float alpha;
int val1 = 1; // integer values, because counter is not float
int val2 = 1;
int val3 = 1;
float inbtw1; // float values, used for calculations with sine wave
float inbtw2;
float inbtw3;
cx++; // Refresh counter
// honestly 0..1799 relates to 1800 steps
if (cx>1799) //If reached maximum then reset
{
cx = 1;
}
alpha = pi2ff * (float)cx * recip1799;
if (parameter == 1) //If direct phase sequence
{
inbtw1=scalefactor*sinf(alpha); // Calculate value of sinus wave
val1=(int)((inbtw1 + 1.0)*170f * 0.5f); // Shift value (only positive values are accepted) and convert to int
//same for other phases
inbtw2=scalefactor*sinf(alpha + phase120);
val2=(int)((inbtw2 + 1.0)*170f * 0.5f);
// note +120 and -120phase shift
inbtw3=scalefactor*sinf(alpha - phase120);
val3=(int)((inbtw3 + 1.0)*170f * 0.5f);
}
else if (parameter==2)// If indirect phase sequence
{
inbtw1=scalefactor*sinf(alpha);
val1=(int)((inbtw1 + 1.0)*170f * 0.5f);
inbtw2=scalefactor*sinf(alpha - phase120);
val2=(int)((inbtw2 + 1.0)*170f * 0.5f);
inbtw3=scalefactor*sinf(alpha + phase120);
val3=(int)((inbtw3 + 1.0)*170f * 0.5f);
}
if (val1 <
1
)
val1
=1;
if (val2 < 1)
val2
=
1
;
if (val3 < 1)
val3
=
1
;
TIM1->CCR1=val1;
TIM1->CCR2=val2;
TIM1->CCR3=val3;
// IRQ handling
HAL_NVIC_ClearPendingIRQ(TIM1_CC_IRQn); //reset pending flag
HAL_TIM_IRQHandler(&htim1); //continue
}
2015-02-10 01:25 AM
I have tested it today in the lab and it worked properly. Thanks again!