In this tutorial, I will show you how to generate PWM signal on STM32 Microcontroller.
You will learn,
- How to enable and configure PWM peripheral using STM32CubeMX.
- Modify code for generating PWM signal with chosen frequency and duty cycle.
- Build and Flash code on Nucleo-F334 board and Test and Observe output using Logic Analyzer.
STM32F334 Features
- Core: Arm® Cortex®-M4 32-bit CPU with FPU (Floating Point Unit) up to 72 MHz.
- Memory: Up to 64 KB Flash, 12 KB SRAM.
- Analog: Fast 12-bit ADCs (5 Msps), Comparators, Op-Amp, DACs.
- Timers: High-resolution Timer (HRTIM), Motor Control Timer, General-purpose Timers.
- Communication: I2C, SPI, up to 3 USARTs, CAN.
- Power: Comprehensive power-saving modes.
Pulse Width Modulation (PWM)
Pulse Width Modulation commonly known as PWM method of representing a signal by using Rectangular wave. It is widely used in Control circuitry.
Key components of PWM signals are Duty Cycle and Period of Square wave signal.
- Duty Cycle
Ratio of ON time to TOTAL time of Rectangular signal.
Duty Cycle = (Ton) / (Ttotal) - Period
Total time of PWM signal.
Common applications of PWM are,
- Motor Speed Control
- LED Brightness Dimming
- Audio Amplification
- Power Supply Regulation
- Heating and Cooling systems
Prerequisite
Before proceeding further make sure you have installed STM32CubeIDE and STM32CubeMX. Links to download both are as below,
Hardware Used
In this tutorial we are using below hardware,
Project Creation and Settings
We are going to use 2 different software from STMicroelectronics,
STM32CubeMX
STM32CubeMX is a graphical tool that allows a very easy configuration of STM32 microcontrollers and microprocessors, as well as the generation of the corresponding initialization C code for the Arm® Cortex®‑M core or a partial Linux® Device Tree for the Arm® Cortex®‑A core, through a step-by-step process.
STM32CubeIDE
STM32CubeIDE is eclipse based IDE with an advanced C/C++ development platform with peripheral configuration, code generation, code compilation, and debug features for STM32 microcontrollers and microprocessors.
STM32CubeMX Steps,
To know how to create a New Project for STM32 using STM32CubeMX and use it with STM32CubeIDE, Follow my previous post.
How to use DMA with UART on STM32 - STM32CubeIDE STM32CubeMX
After Creating project using steps mentioned in above post. do changes using steps mentioned below.
- Set main clock of Microcontroller to 64MHZ following steps in above tutorial
- Click on Timer Tab on Left Side List and TIM1, It will settings related to TIM1.
For TIM1 timer, do below mentioned changes in "TIM1 Mode and Configuration" window. - Clock Source : Internal Clock
- Channel1 : PWM Generation CH1
- Channel2 : PWM Generation CH2
- In TIM1 Configuration window, We will set Timer Prescaler, Counter and other settings.
Do below mentioned settings for TIM1 Counter Settings Selection. - Prescaler : 0
- Counter Period : 6400
- Here, I have selected PC0 and PC1 for TIM1 Channel 1 & 2.
- Generate Code to STM32CubeIDE workspace location.
- Import generated project into STM32CubeIDE and Do the modification in code as given in source code on GitHub repository.
Code
uint16_t PWM_Count = 6400;
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
PWM_Count += 500;
if(PWM_Count >= 6400) PWM_Count = 0;
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,6400 - PWM_Count);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,PWM_Count);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
Explanation of Code
Let us first understand calculation for PWM period and Duty Cycle settings.
- TIM1 Input Clock = 64MHZ
- PWM Frequency = 10KHZ
TIM1 Counter Period Register (AutoReload Register)
= TIM Input Clock Frequency / PWM Output Frequency
= (64MHZ) / (10KHZ)
= 6400
To Control Duty Cycle of PWM Signal, PWM Channel Pulse Register will be used.
In Code, First we have a variable to track and modify PWM Duty Cycle.
uint16_t PWM_Count = 6400;Below function calls enables and starts PWM signal generation on TIM1 Channel 1 and 2.
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);Below block of Code, Changes Duty Cycle of PWM Signal on both channels.
I have increased PWM Duty Cycle of PWM Signal, every seconds. It will increase Duty Cycle from 0 to 100 and repeat.
I have increased PWM Duty Cycle of PWM Signal, every seconds. It will increase Duty Cycle from 0 to 100 and repeat.
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
PWM_Count += 500;
if(PWM_Count >= 6400) PWM_Count = 0;
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,6400 - PWM_Count);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,PWM_Count);
HAL_Delay(1000);
/* USER CODE END WHILE */Full Project Code
You can directly download and use whole project from below GitHub link.
GitHub Repo Link
Working Of Code
Below video shows working of this project. Code at boot up will start generating PWM Signals on TIM1 Channel 1 and 2 using PC0 and PC1 Pins. Code will increase PWM Duty Cycle every seconds up to 100% and will repeat.
Wrapping Up
In todays tutorial, You have learned how to generate PWM Signal using TIM1. How to configure TIM1 peripheral including Counter, Prescaler and other settings.
Please leave a comment if you have a question or you found this tutorial helpful.
0 Comments