Skip to main content
M7890.1
Associate III
September 12, 2021
Solved

How to generate PWM and use timer interrupt at the same time?

  • September 12, 2021
  • 4 replies
  • 18171 views

I am using the Bluepill board. I want to generate PWM signal on Timer2 and set up a timer interrupt at 20ms interval on Timer3. I realized that the PWM signal cannot be generated if I set up the timer interrupt on Timer3. How do I solve this problem?

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

> left_pwm / 1000000

> right_pwm / 1000000

These always evaluate to 0. If you want to use float, cast them to float first instead.

	TIM2->CCR1 = (int) ((((float) left_pwm / 1000000) / 0.02) * 65535);
	TIM2->CCR2 = (int) ((((float) right_pwm / 1000000) / 0.02) * 65535);

4 replies

TDK
September 12, 2021

You can have PWM generation on one timer and update interrupt on another timer at the same time. What issue are you running into? They are independent.

"If you feel a post has answered your question, please click ""Accept as Solution""."
M7890.1
M7890.1Author
Associate III
September 12, 2021

Yes. They should be independent. So I was having these 3 lines before my while loop:

HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);	// start PWM signal
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
 
HAL_TIM_Base_Start_IT(&htim3);

I have set my PWM pulse width to 1ms. When I take a look at the output, the PWM output a single pulse of 1ms and it becomes zero after that (most probably after timer3 being started). If I remove HAL_TIM_Base_Start_IT(&htim3); from my code, the PWM signal can be generated without problem.

waclawek.jan
Super User
September 12, 2021

> The problem happens due to the CCR1 and CCR2 being updated.

To what values?

JW

S.Ma
Principal
September 12, 2021

Don t do float calculation inside a callback.

MM..1
Chief III
September 12, 2021

@M7890.1​  Your problem is simple left_pwm uint16 / 1000000 is always 0

TDK
TDKBest answer
September 12, 2021

> left_pwm / 1000000

> right_pwm / 1000000

These always evaluate to 0. If you want to use float, cast them to float first instead.

	TIM2->CCR1 = (int) ((((float) left_pwm / 1000000) / 0.02) * 65535);
	TIM2->CCR2 = (int) ((((float) right_pwm / 1000000) / 0.02) * 65535);

"If you feel a post has answered your question, please click ""Accept as Solution""."
Piranha
Principal III
September 29, 2021

The constant 0.02 is of a double type and because of the brackets there will be double operations, including the division, at runtime. One can write 0.02f to use a float type, but in this case the whole expression can be reordered into much more efficient.

TIM2->CCR1 = (float)left_pwm * (float)(65535 / 0.02 / 1000000);

No double operations at runtime, no divisions at all - just a single multiplication at runtime.