Skip to main content
Associate
March 19, 2025
Solved

PWM Duty cycle control with __HAL_TIM_SET_COMPARE

  • March 19, 2025
  • 4 replies
  • 1473 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

4 replies

KnarfB
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
Associate
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 

KnarfB
KnarfBBest answer
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
Associate
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.