Microcontroller PWM Output Techniques

Follow+Star Public Account Number, don’t miss out on exciting contentAuthor | strongerHuangWeChat Public Account | Embedded ColumnIn our daily lives, many electronic products utilize PWM, such as cars, refrigerators, washing machines, fans, lighting, toys, etc.Perhaps you may not feel its presence, but it is hidden within countless electronic products around us.Here, I will share some common uses of PWM as many fans have asked questions related to it.

What is PWM?

PWM: Pulse Width Modulation.

There are many explanations online, and through the following diagram, you can intuitively understand PWM, which is essentially a pulse signal composed of high and low levels.

Microcontroller PWM Output Techniques

By changing the frequency (pulse period) and duty cycle, it can be applied in many scenarios.

Microcontroller PWM Output Techniques

Common PWM Output Methods

From the above description, PWM is an IO port that outputs high and low levels at different time periods.1. Beginner Level (Novice) Using a while loop with blocking delay to control IO high and low output:

while(1){  IO high level  Delay blocking delay  IO low level  Delay blocking delay}

Blocking delay can be: software simulated delay, timer blocking delay, etc.2. Entry Level (Junior) Using a while loop with non-blocking delay to control IO high and low output:

while(1){  IO high level  Delay non-blocking delay  IO low level  Delay non-blocking delay}

Non-blocking delay can be: timer flag detection, RTOS (system) delay, etc.3. Familiar Level (Intermediate) Using timer interrupts to control IO high and low output:

Timer interrupt configuration -> Start timer -> Respond to interrupt, control IO high and low levels…

4. Proficient Level (Intermediate+) Using timer PWM hardware control output:

Configure the corresponding IO for PWM, and timer PWM output -> Start PWM automatic output…

void AppTask(void *p_arg){  PWM_TIM_Configuration();  PWM_Output(frequency, dutyCycle);  while(1)  {    // Your application code  }}

Comparison:Among the above PWM output methods, the first three require CPU intervention for PWM output, which occupies CPU resources, especially the first two methods, which not only occupy CPU but also have larger errors.Using the third interrupt method, if the frequency is relatively high, the CPU consumption is also quite significant. This method is suitable for microcontrollers without hardware PWM output.The fourth method utilizes the built-in hardware PWM output function of the microcontroller, which only requires simple configuration to automatically output PWM waveforms without CPU intervention.

Example of Hardware PWM Output

Here, we take the familiar STM32F1 as an example to briefly share the hardware timer output PWM waveform.PWM Timer Related Macro Definitions:

// Timer counting clock (1M times/second)#define PWM_COUNTER_CLOCK         1000000   // Prescaler value (related to system clock and count value)#define PWM_PRESCALER_VALUE       (SystemCoreClock/PWM_COUNTER_CLOCK - 1)

PWM Configuration:

/**  * @brief  Timer PWM output configuration  * @param  None  * @retval None  */void PWM_TIM_Configuration(void){  GPIO_InitTypeDef        GPIO_InitStructure;  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  TIM_OCInitTypeDef       TIM_OCInitStructure;  /* Clock configuration */  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);  /* Pin configuration */  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;  GPIO_Init(GPIOA, &GPIO_InitStructure);  /* Time base configuration */  TIM_TimeBaseStructure.TIM_Prescaler = PWM_PRESCALER_VALUE;         // Prescaler value  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;        // Up counting  TIM_TimeBaseStructure.TIM_Period = 0xFFFF;                         // Timer period (temporary value)  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;            // Division factor  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  /* PWM mode configuration */  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                  // Output PWM1 mode  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;      // Enable output  TIM_OCInitStructure.TIM_Pulse = 0;                                 // Pulse width value (temporary value)  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;          // Output polarity (TIM_OC1 corresponds to channel 1)  TIM_OC1Init(TIM2, &TIM_OCInitStructure);}

PWM Output Function Interface:

/*** @brief  Output PWM  * @param  Frequency: frequency                      Dutycycle: duty cycle  * @retval None  */void PWM_Output(uint32_t Frequency, uint32_t Dutycycle){  uint32_t tim_period;  uint32_t tim_pulse;  tim_period = PWM_COUNTER_CLOCK/Frequency - 1;                      // Calculate counting period (determines output frequency)  tim_pulse  = (tim_period + 1)*Dutycycle / 100;                     // Calculate pulse width value (determines PWM duty cycle)  TIM_Cmd(TIM2, DISABLE);                                            // Disable TIM  TIM_SetCounter(TIM2, 0);                                           // Clear counter  TIM_SetAutoreload(TIM2, tim_period);                               // Change frequency  TIM_SetCompare1(TIM2, tim_pulse);                                  // Change duty cycle (TIM_SetCompare1 corresponds to channel 1)  TIM_Cmd(TIM2, ENABLE);                                             // Enable TIM}

Initialize configuration, call function interface, and directly output PWM waveforms:

void AppTask(void *p_arg){  PWM_TIM_Configuration();  PWM_Output(1000, 20);  while(1)  {    // Application code  }}

Output PWM Waveform:

Microcontroller PWM Output TechniquesNote:This example uses the STM32 Standard Peripheral Library. If you want to understand the principles in depth, it is recommended to use the Standard Peripheral Library.

Of course, if you want to quickly use the PWM function without understanding its principles, you can directly use STM32CubeMX to configure and generate code:

Microcontroller PWM Output Techniques

Configuration Considerations

To achieve more precise control and better meet application layer requirements, you need to understand the principles step by step.Here are some common issues:1. Pin MappingIf the pin you are using requires mapping, you need to configure the corresponding parameters.For example: STM32F1 uses PB11 (refer to the datasheet):Microcontroller PWM Output TechniquesYou need to add the corresponding “mapping” code:

// Multiplexing functionRCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);// Timer (PWM) pin mappingGPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE);

2. Frequency and Duty Cycle PrecisionIf you use a 32-bit timer, the frequency range is wider, and the precision can be higher. For example: frequency: 0.01Hz, duty cycle 0.01%, etc.If it is 16 bits, the parameters cannot exceed 16 bits (65535):

#define PWM_COUNTER_CLOCK         1000000#define PWM_PRESCALER_VALUE       (SystemCoreClock/PWM_COUNTER_CLOCK - 1)tim_period = PWM_COUNTER_CLOCK/Frequency - 1;                      // Calculate counting period (determines output frequency)tim_pulse  = (tim_period + 1)*Dutycycle / 100;                     // Calculate pulse width value (determines PWM duty cycle)

Specific configurations can be made according to your situation, such as PWM (timer) counting clock, prescaler value, etc.In actual application code, it is recommended to add checks for each parameter to prevent overflow (this is written simply for understanding)..3. MoreSTM32 has hardware PWM output functions, but different series may have slight differences in configuration. Refer to the official examples and manuals.Currently, most microcontrollers come with hardware PWM output functions, which do not require CPU intervention. If not, you can try the timer interrupt method mentioned above.———— END ————Microcontroller PWM Output Techniques● Column “Embedded Tools”● Column “Embedded Development”● Column “Keil Tutorials”● Selected Tutorials from Embedded ColumnFollow the public accountReply “Join Group” to join the technical exchange group according to the rules, reply “1024” to see more content.Click “Read the Original” to see more shares.

Leave a Comment