Skip to main content
lk1991
Associate II
February 6, 2015
Question

TIM1 CCR3 Register Problem? STM32F429

  • February 6, 2015
  • 9 replies
  • 1618 views
Posted on February 06, 2015 at 17:29

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;
    This topic has been closed for replies.

    9 replies

    waclawek.jan
    Super User
    February 6, 2015
    Posted on February 06, 2015 at 17:41

    Let me guess: value1, value2 and value3 in the first instance are uninitialized local variables?

    JW
    Tesla DeLorean
    Guru
    February 6, 2015
    Posted on February 06, 2015 at 17:53

    Preloaded or Immediate?

    Post some actual code that demonstrates your issue.
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    lk1991
    lk1991Author
    Associate II
    February 6, 2015
    Posted on February 06, 2015 at 18:12

    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

    }

    lk1991
    lk1991Author
    Associate II
    February 6, 2015
    Posted on February 06, 2015 at 18:13

    /* 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();
    }
    }

    waclawek.jan
    Super User
    February 6, 2015
    Posted on February 06, 2015 at 19:39

    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.

    JW

    Tesla DeLorean
    Guru
    February 6, 2015
    Posted on February 06, 2015 at 20:48

    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
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    lk1991
    lk1991Author
    Associate II
    February 6, 2015
    Posted on February 06, 2015 at 21:00

    Thanks for the suggestions, I'll try and post results after.

    Tesla DeLorean
    Guru
    February 6, 2015
    Posted on February 06, 2015 at 21:14

    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
    }

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    lk1991
    lk1991Author
    Associate II
    February 10, 2015
    Posted on February 10, 2015 at 10:25

    I have tested it today in the lab and it worked properly. Thanks again!