Zbotic Logo Zbotic Logo
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

  • Shop
  • About Us
  • Contact Us
  • Reseller
  • Blogs
020 69134444
1800 209 0998
[email protected]
Help Desk
Facebook Twitter Instagram Linkedin YouTube
Zbotic Logo Zbotic Logo
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

All departments
  • 3D Print Service
  • 3D Printer
  • Batteries & Chargers
  • Development Boards
  • Drone Parts
  • EBike parts
  • Sensor Modules
  • Electronic Components
  • Electronic Modules
  • IoT and Wireless
  • Mechanical Parts and Workbench Tools
  • Motors & Drivers & Pumps & Actuators
  • DIY and Robot Kits
  • Show more
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
Return to previous page
Home Development Boards & SBCs

STM32 PWM Generation: Timer Configuration and Code Guide

STM32 PWM Generation: Timer Configuration and Code Guide

March 11, 2026 /Posted byJayesh Jain / 0

Mastering STM32 PWM timer configuration and code is essential for motor control, LED dimming, servo positioning, and audio generation. STM32’s advanced timer system with hardware dead-time insertion, complementary outputs, and DMA triggers makes it far more capable than Arduino’s analogWrite for professional PWM generation.

Table of Contents

  • STM32 Timer Architecture
  • Calculating PWM Frequency
  • Basic PWM Output Code
  • Multi-Channel PWM
  • Complementary PWM for H-Bridge
  • Servo Motor Control
  • Frequently Asked Questions

STM32 Timer Architecture

STM32F4 series has up to 14 timers. For PWM:

  • TIM1, TIM8: Advanced-control timers — complementary outputs, dead-time, break input (motor control)
  • TIM2–TIM5: General-purpose 32-bit timers — most flexible for PWM applications
  • TIM9–TIM14: Basic timers — limited channel count

Each timer channel can be mapped to specific GPIO pins (alternate functions). STM32CubeMX shows which pins correspond to which timer channel — critical knowledge for PCB design in Indian hardware products.

Recommended: Arduino UNO R3 Development Board ATMEGA16U2 ATMEGA328P (DIP) — Arduino UNO R3 — Arduino’s analogWrite() provides basic PWM for prototyping; STM32 timers replace it for production with hardware-precise waveforms.

Calculating PWM Frequency

PWM frequency formula: f_PWM = f_TIMclk / ((PSC + 1) × (ARR + 1))

Example: 20 kHz PWM on STM32F411 (APB1 clock = 50 MHz for TIM2):

// Target: 20 kHz PWM
// f_TIMclk = 100 MHz (TIM2 on APB1 × 2 on STM32F411)
// PSC = 0 (no prescaling)
// ARR = f_TIMclk / f_PWM - 1 = 100,000,000 / 20,000 - 1 = 4999
// Resolution: 5000 steps (0.02% duty cycle steps)

// In CubeMX:
// TIM2 → Clock source: Internal Clock
// PSC: 0
// Counter Period (ARR): 4999
// PWM Channel → Pulse (CCR): 0 to 4999 = 0% to 100% duty

Basic PWM Output Code

/* STM32 HAL PWM on TIM2 Channel 1 (PA0) */
#include "stm32f4xx_hal.h"

TIM_HandleTypeDef htim2;
TIM_OC_InitTypeDef sConfigOC = {0};

void MX_TIM2_Init(void) {
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 4999;        // 20 kHz at 100 MHz
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_PWM_Init(&htim2);
  
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 2500;          // 50% duty cycle
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
}

// Start PWM
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

// Change duty cycle dynamically
void setPWMDutyCycle(uint32_t duty_percent) {
  uint32_t pulse = (htim2.Init.Period + 1) * duty_percent / 100;
  __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, pulse);
}
Recommended: Waveshare RP2350-Plus Development Board — RP2350-Plus — also supports PWM on all GPIO pins with 16 PWM slices, excellent for servo and LED dimming with MicroPython’s machine.PWM API.

Multi-Channel PWM

TIM2 on STM32F4 has four channels (CH1–CH4), each with independent duty cycle but sharing the same frequency. This is ideal for multi-servo control or RGB LED dimming with synchronised timing:

// Configure and start 3 PWM channels on TIM2 for RGB LED
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1); // Red
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2); // Green
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3); // Blue

HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);

// Set RGB colour
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, r * 5000 / 255);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, g * 5000 / 255);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, b * 5000 / 255);

Complementary PWM for H-Bridge

TIM1’s advanced feature for motor H-bridge control: complementary outputs on CH1 and CH1N with configurable dead time to prevent shoot-through.

/* TIM1 Complementary PWM with dead-time */
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE;
sBreakDeadTimeConfig.DeadTime = 20;  // ~150 ns dead time at 168 MHz

HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);

// Start complementary channels
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1); // PA8 (CH1) and PB13 (CH1N)
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);

Servo Motor Control

/* Servo control on TIM3 CH1 at 50Hz (20ms period) */
// At 1 MHz timer clock (PSC=99 for 100 MHz): ARR = 19999
// 1ms pulse = 1000 counts (0 degrees)
// 2ms pulse = 2000 counts (180 degrees)
void setServoAngle(uint8_t angle) {
  uint32_t pulse = 1000 + (angle * 1000 / 180); // 1000-2000
  __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pulse);
}

Frequently Asked Questions

What PWM frequency is best for motor speed control in Indian robotics?

For DC motors with L298N or DRV8833: 10–25 kHz is ideal (above audible frequency, reduces motor heating). For servo motors: 50 Hz is standard (20ms period). For brushless motors (ESC): 50 Hz standard pulse or 400 Hz fast protocol.

Can I change PWM frequency dynamically on STM32?

Yes. Modify ARR (auto-reload register) while timer runs. Use __HAL_TIM_SET_AUTORELOAD() to change period, but adjust pulse values proportionally to maintain duty cycle.

How many simultaneous PWM channels can STM32F103 generate?

STM32F103 has seven timers with up to 4 channels each. In practice, 10–12 independent PWM channels are achievable simultaneously — far more than Arduino Uno’s 6.

Shop Development Boards & SBCs at Zbotic →

Tags: PWM motor control STM32, STM32 HAL PWM, STM32 PWM, STM32 servo control, STM32 timer PWM, STM32F4 timer India
Share Post
  • Facebook
  • Linkedin
  • Whatsapp
DIY Bluetooth Speaker: PAM8403...
blog diy bluetooth speaker pam8403 and bluetooth audio module 599151
blog solar street light circuit led driver and battery system 599155
Solar Street Light Circuit: LE...

Related posts

Svg%3E
Read more

Battery Charger Module TP4056: LiPo and 18650 Charging Guide

April 1, 2026 0
The TP4056 battery charger module is one of the most essential components for any battery-powered electronics project. Costing under ₹30,... Continue reading
Svg%3E
Read more

Buck Converter vs Boost Converter: Voltage Regulation Guide

April 1, 2026 0
Understanding buck converters vs boost converters is essential for every electronics project involving power management. Whether you are stepping down... Continue reading
Svg%3E
Read more

Google Coral TPU: Accelerating AI Projects on Raspberry Pi

April 1, 2026 0
The Google Coral TPU (Tensor Processing Unit) transforms a Raspberry Pi from a sluggish AI hobbyist tool into a real-time... Continue reading
Svg%3E
Read more

NVIDIA Jetson Nano Projects India: Getting Started Guide

April 1, 2026 0
The NVIDIA Jetson Nano is the most accessible GPU-accelerated AI computer for developers in India. With 128 CUDA cores, a... Continue reading
Svg%3E
Read more

ATtiny85 Projects: Tiny Microcontroller for Space-Constrained Builds

April 1, 2026 0
The ATtiny85 is the Swiss Army knife of tiny microcontrollers — just 8 pins, 8 KB of flash, and a... Continue reading

Add comment Cancel reply

Your email address will not be published. Required fields are marked

Facebook Twitter Instagram Pinterest Linkedin Youtube

Get the latest deals and more.

Download on Google Play Download on the App Store

Call us: 020 69134444 / 1800 209 0998

Monday - Saturday 09:30 AM - 06:00 PM
For Technical Supports Email: [email protected]
For Sales / Enquiries Email: [email protected]

  • My Account

    • Cart

    • Wishlist

    • Checkout

    • My Orders

    • Track Order

    • My Account

  • Information

    • FAQs

    • Blogs

    • Career

    • About Us

    • Contact Us

    • Payment Options

  • Policies

    • Privacy Policy

    • Terms & Conditions

    • GST Input Tax Credit

    • Shipping Return Policy

    • E-Waste Collection Points

    • Our Sitemap

© Zbotic.in is registered trademark of Moxie Supply Pvt Ltd – All Rights Reserved
Login
Use Phone Number
Use Email Address
Not a member yet? Register Now
Reset Password
Use Phone Number
Use Email Address
Register
Already a member? Login Now