Skip to main content
Visitor II
March 19, 2025
Solved

PWM Duty cycle control with __HAL_TIM_SET_COMPARE

  • March 19, 2025
  • 3 replies
  • 1326 views

I am working on a project that I aim to control a boost converter using a stm32 f407 disc kit. I want to control pwm duty cycle with two different integers which are x and y. I want my duty cycle equal to (1-(x/y)) how can I do it

    This topic has been closed for replies.
    Best answer by KnarfB

    The types of variables are not shown in the code. Make all conversions in float and convert to uint16_t at the very end.

    Also use step-by-step debugging and live expresssion watching to follow the calculations.

    Good luck

    KnarfB

    3 replies

    Super User
    March 19, 2025

    Suppose the timer TIM1 is in up-counting mode and you have configured TIM1 channel 2 to PWM output mode.

    Then, the ARR register (together with the prescaler...) determines the PWM frequency,

    and the channel's CCR2 register determines the active phase (duty cycle) of the PWM.

    The registers hold unsigned integers, mostly 16-bit, some timer(s) 32-bit.

    So, you must find your way to expand the above fraction to suitable integer calculations.

    Or, you use float, like so

    float x = ...;
    float y = ...;
    float duty = 1.0f - (x/y);
    TIM1->ARR = ...; // set once, depending on PWM freq.
    TIM1->CCR2 = (uint16_t)(duty * TIM1->ARR);

    If you use HAL, there are __HAL macros for that: 

    __HAL_TIM_GET_AUTORELOAD, 
    __HAL_TIM_SET_COMPARE

    hth

    KnarfB

    EmirUysalAuthor
    Visitor II
    March 19, 2025
    HAL_ADC_Start(&hadc1);
    
    if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)
    
    { adc_value = HAL_ADC_GetValue(&hadc1); }
    
    HAL_ADC_Stop(&hadc1);
    
    adc_voltage = (adc_value * 30.5) / 4095;
    
    HAL_ADC_Start(&hadc2);
    
    if (HAL_ADC_PollForConversion(&hadc2, 100) == HAL_OK)
    
    { pot_value = HAL_ADC_GetValue(&hadc2); }
    
    HAL_ADC_Stop(&hadc2);
    
    pot = (pot_value * (35 - 12)) / 4095 + 12;
    
    duty_cycle = (1.0f - (adc_voltage / pot)) * 500;
    
    TIM2->CCR1 = duty_cycle;

    I type this code and only I can get 0 or 500 for duty cycle but if I write CCR1 by myself like 300 or 200 it is working as my desire 

    KnarfBAnswer
    Super User
    March 19, 2025

    The types of variables are not shown in the code. Make all conversions in float and convert to uint16_t at the very end.

    Also use step-by-step debugging and live expresssion watching to follow the calculations.

    Good luck

    KnarfB

    EmirUysalAuthor
    Visitor II
    March 19, 2025

    All I have to do is type uint32_t at the very end. 

    Thanks for everything. I can not done it without that information.