Pulse Width Modulation (PWM), short for "Pulse Width Modulation", is a very effective technology that uses the digital output of a microprocessor to control analog circuits. To put it simply, it is the control of pulse width. It is generally used to control the speed of a stepper motor, etc.
Except for TIM6 and TIM7, all other timers of STM32 can be used to generate PWM outputs. The advanced timers TIM1 and TIM8 can generate 7-channel PWM outputs at the same time, and the general timer can also generate 4-channel PWM outputs at the same time.
1.1 PWM output mode
The STM32 PWM output has two modes, Mode 1 and Mode 2, which are determined by the OCxM bit in the TIMx_CCMRx register ("110" is Mode 1, "111" is Mode 2). The differences between Mode 1 and Mode 2 are as follows:
110: PWM mode 1 - When counting up, channel 1 is at a valid level once TIMx_CNT, otherwise it is at an invalid level; when counting down, channel 1 is at an invalid level (OC1REF=0) once TIMx_CNT>TIMx_CCR1, otherwise it is at a valid level (OC1REF=1).
111: PWM mode 2 - When counting up, channel 1 is at an invalid level once TIMx_CNT, otherwise it is at a valid level; when counting down, channel 1 is at a valid level once TIMx_CNT>TIMx_CCR1, otherwise it is at an invalid level.
From this point of view, Mode 1 and Mode 2 complement each other and are opposite to each other, so there is not much difference in their application.
From the counting mode point of view, PWM also has up counting mode, down counting mode and center alignment mode just like TIMx when it is used as a timer. For specific information about the three modes, please refer to the "14.3.9 PWM Mode" section of the "STM32 Reference Manual". I will not go into details here.
1.2 PWM output pin
The output pins of PWM are determined. For specific pin functions, please refer to the "8.3.7 Timer Multiplexing Function Remapping" section of the "STM32 Reference Manual". It should be emphasized here that different TIMx have different pins assigned, but considering the pin multiplexing function, STM32 proposes a concept of remapping, that is, by setting some related registers, PWM can be output on other non-originally designated pins. However, these remapped pins are also given by the reference manual. For example, the second channel of TIM3, when there is no remapping, the designated pin is PA.7. If partial remapping is set, the output of TIM3_CH2 is mapped to PB.5. If full remapping is set, the output of TIM3_CH2 is mapped to PC.7.
1.3 PWM output signal
PWM outputs a square wave signal, the frequency of which is determined by the TIMx clock frequency and the TIMx_ARR prescaler. The specific setting method is explained in detail in the previous study notes. The duty cycle of the output signal is determined by the TIMx_CRRx register. The formula is "duty cycle = (TIMx_CRRx/TIMx_ARR)*100%", so you can output a square wave signal with the frequency and duty cycle you need by filling in the appropriate number in CRR.
2. TIMER output PWM implementation steps
1. Set the RCC clock;
2. Set the GPIO clock;
3. Set the relevant registers of TIMx timer;
4. Set the PWM related registers of the TIMx timer.
Step 1 Setting the RCC clock has been given in detail in the previous article, so I will not repeat it here. It should be noted that the general timer TIMx is clocked by APB1, while the GPIO is clocked by APB2. Note that if you need to reimage the PWM output, you also need to enable the pin multiplexing clock AFIO.
When setting the GPIO clock in step 2, the GPIO mode should be set to multiplexed push-pull output GPIO_Mode_AF_PP. If pin remapping is required, it needs to be set using the GPIO_PinRemapConfig() function.
Step 3: When setting the relevant registers of the TIMx timer, just like the previous study note, set the relevant TIMx clock and technology mode, etc. For specific settings, please refer to the study notes of "TIMER basic timing function".
Step 4 sets the PWM related registers. First, set the PWM mode (PWM is frozen by default), then set the duty cycle (calculated according to the formula described above), and then set the output comparison polarity: when set to High, the output signal is not inverted, and when set to Low, the output signal is inverted before output. The most important thing is to enable the output state of TIMx and enable the PWM output of TIMx.
After the relevant settings are completed, the TIMx timer can be turned on through TIM_Cmd() to obtain PWM output.
3. TIMER output PWM source code
Since the Struggle development board I have now connects PB.5 to the LED, it is necessary to use the CH2 channel of TIM3 and remap the pins. After turning on TIM3, PWM output makes the LED light up, and the brightness of the LED can be adjusted by changing the duty cycle in PWM_cfg().
#include "stm32f10x_lib.h"
void RCC_cfg();
void GPIO_cfg();
void TIMER_cfg();
void PWM_cfg();
//Duty cycle, the value range is 0-100
int dutyfactor = 50;
int main()
{
int Temp;
RCC_cfg();
GPIO_cfg();
TIMER_cfg();
PWM_cfg();
// Enable TIM3 timer and start outputting PWM
TIM_Cmd(TIM3, ENABLE);
while(1);
}
void RCC_cfg()
{
//Define error status variable
ErrorStatus HSEStartUpStatus;
//Reset the RCC register to the default value
RCC_DeInit();
// Turn on the external high-speed clock crystal
RCC_HSEConfig(RCC_HSE_ON);
[page]
//Wait for the external high-speed clock crystal to work
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSESTartUpStatus == SUCCESS)
{
//Set AHB clock (HCLK) as system clock
RCC_HCLKConfig(RCC_SYSCLK_Div1);
//Set the high-speed AHB clock (APB2) to HCLK clock
RCC_PCLK2Config(RCC_HCLK_Div1);
//Set the low-speed AHB clock (APB1) to 2 times the frequency of HCLK
RCC_PCLK1Config(RCC_HCLK_Div2);
//Set FLASH code delay
FLASH_SetLatency(FLASH_Latency_2);
// Enable prefetch cache
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//Set the PLL clock to 9 times the HSE frequency 8MHz * 9 = 72MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
// Enable PLL
RCC_PLLCmd(ENABLE);
//Wait for PLL to be ready
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
//Set PLL as system clock source
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
//Judge whether PLL is the system clock
while(RCC_GetSYSCLKSource() != 0x08);
}
//Turn on the TIM3 clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
// Enable the clock and multiplexing functions of GPIOB
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);
}
void GPIO_cfg()
{
GPIO_InitTypeDef GPIO_InitStructure;
//Partial mapping, map TIM3_CH2 to PB5
//GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
//Select pin 5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
//Output frequency up to 50MHz
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//Multiplex push-pull output
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB,&GPIO_InitStructure);
}
void TIMER_cfg()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//Reset the Timer to its default value
TIM_DeInit(TIM3);
//Use the internal clock to provide the clock source for TIM3
TIM_InternalClockConfig(TIM3);
//The pre-scaling coefficient is 0, that is, no pre-scaling is performed, and the frequency of TIMER is 72MHz
TIM_TimeBaseStructure.TIM_Prescaler = 0;
//Set the clock division
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
//Set the counter mode to up counting mode
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
//Set the count overflow size, and generate an update event every 7200 counts, that is, the PWM output frequency is 10kHz
TIM_TimeBaseStructure.TIM_Period = 7200 - 1;
//Apply the configuration to TIM3
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
}
void PWM_cfg()
{
TIM_OCInitTypeDef TimOCInitStructure;
//Set the default value
TIM_OCStructInit(&TimOCInitStructure);
//PWM mode 1 output
TimOCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
//Set the duty cycle, duty cycle = (CCRx/ARR)*100% or (TIM_Pulse/TIM_Period)*100%
TimOCInitStructure.TIM_Pulse = dutyfactor * 7200 / 100;
//TIM output comparison polarity high
TimOCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
// Enable output status
TimOCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
//CH2 output of TIM3
TIM_OC2Init(TIM3, &TimOCInitStructure);
//Set TIM3 PWM output to enable
TIM_CtrlPWMOutputs(TIM3,ENABLE);
}
Previous article:STM32 Study Notes 6 (TIM module timer)
Next article:STM32 learning notes (4): basic timing functions of general timers
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- Testing of heating power of NOx sensor
- IoT access terminal
- How to Measure Cable Impedance and Loss Using a Vector Network Analyzer
- Make Magazine: Getting started with Python on hardware
- Does the LCD module need to be grounded when used?
- 【BLE 5.3 wireless MCU CH582】11. Mobile app controls the LED on and off
- Registration for the 2021 STM32 National Tour Seminar is now open!
- Flexible use of software to simulate PA parameter changes
- After reading this article, do you have the urge to make some modifications? Let's take a look at the design of an outdoor camera with a temperature switch.
- IIC waveform improvement