First, some necessary declarations
#include#include "pwm.h"u32 Sys_Clk=1000000;u16 pwm1_2_Freqz;//Frequency of pwm wave 1, 2 output port u16 pwm3_4_Freqz;//Frequency of pwm wave 3, 4 output port u16 TIM2_PERIOD;//Number of timer jump cycles u16 TIM4_PERIOD;u16 CCR_VAL1;//Value of the timer comparison register, when the actual value is greater than this value, the level is inverted u16 CCR_VAL2; u16 CCR_VAL3; u16 CCR_VAL4; 123456789101112
Below is the main text... The notes are all typed by hand (≧▽≦)/
void PWM_GPIO_Config(void) //Function used to configure peripheral functions, always ends with the string "Config" { GPIO_InitTypeDef GPIO_InitStructure; //PPP_InitTypeDef: Initialize the peripheral named PPP, here is to initialize GPIO RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);//Turn on the clock, status: ENABLE means enabled. Periph means peripheral device in Chinese. Initialize GPIO AB port, multiplex push-pull output RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //Turn on TIM2 clock For the classification of APB1 and APB2, see Figure 1 and Figure 2 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3; //Initialize pins 2,3 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //Select one of the enumeration types GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //Frequency 50 MHz GPIO_Init(GPIOA,&GPIO_InitStructure); //Initialize port A RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); //Turn on TIM4 clock /*Configure PB8 and PB9 to multiplex push-pull mode*/ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8|GPIO_Pin_9; //Same as before GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure); }123456789101112131415161718192021
OK. We just configured the GPIO pins for the pwm output.
Next we configure the pwm clock.
void PWM_Mode_Config(void)//Configure pwm mode { TIM4_PERIOD=Sys_Clk/pwm1_2_Freqz; //Timer jump cycle number = system clock cycle/pwm output frequency TIM2_PERIOD=Sys_Clk/pwm3_4_Freqz; CCR_VAL1=CCR_VAL2=TIM4_PERIOD>>1; //Shift operation to make the value of the comparison register equal to half of the jump cycle number, and obtain a PWM wave with a duty cycle of 50% CCR_VAL3=CCR_VAL4=TIM2_PERIOD>>1; /*Timer (ie TIM) initialization*/ TIM_TimeBaseStructure.TIM_Period = TIM4_PERIOD; //Set the period value to be loaded into the auto-reload register in the next update event, for TIM4 TIM_TimeBaseStructure.TIM_Prescaler=72; //Prescaler value TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //Clock division TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //Upward counting mode TIM_TimeBaseInit(TIM4, & TIM_TimeBaseStructure); //Initialize TIM4 according to the parameters specified in TIM_TimeBaseStructure TIM_TimeBaseStructure.TIM_Period = TIM2_PERIOD; //Set the period value to be loaded into the auto-reload register in the next update event, for TIM4. Other parameters are the same as TIM2, so they are not set again. TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure); //Initialize TIM2 according to the parameters specified in TIM_TimeBaseStructure /*Timer output mode initialization*/ TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1; //TIM_OCInitStruct is after TIM_OCInitTypeDef (Figure 3), the structure has multiple parameters. This line sets the pulse width modulation mode 1 TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable; //Comparison output enable TIM_OCInitStruct.TIM_Pulse=CCR_VAL4; //Set duty cycle to 50% TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High; //Set the effective polarity, that is, set the effective level of the comparison output. Here it is set to high level effective. When the timer compares and matches, the output port outputs a high level TIM_OC3Init(TIM2,&TIM_OCInitStruct); //Initialize TIM2 channel 3 (pwm4) TIM_OC3PreloadConfig(TIM2,TIM_OCPreload_Enable); //After initializing OCX, configure the preload register of OCX and enable it. TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable; //Comparison output enable TIM_OCInitStruct.TIM_Pulse=CCR_VAL3; //Set duty cycle to 50% TIM_OC4Init(TIM2,&TIM_OCInitStruct); //Initialize TIM2 channel 4 (pwm3) TIM_OC4PreloadConfig(TIM2,TIM_OCPreload_Enable); //Configure the preload register of OC4 TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable; //Comparison output enable TIM_OCInitStruct.TIM_Pulse=CCR_VAL2; //Set duty cycle to 50% TIM_OC3Init(TIM4,&TIM_OCInitStruct); //Initialize TIM4 channel 3 (pwm2) TIM_OC3PreloadConfig(TIM4,TIM_OCPreload_Enable); //Configure the preload register of OC3 TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable; //Comparison output enable TIM_OCInitStruct.TIM_Pulse=CCR_VAL1; //Set duty cycle to 50% TIM_OC4Init(TIM4,&TIM_OCInitStruct);/Initialize TIM4 channel 4 (pwm1) TIM_OC4PreloadConfig(TIM4,TIM_OCPreload_Enable); //Configure the preload register of OC4 TIM_ARRPreloadConfig(TIM2, ENABLE); //After configuring all channels, enable automatic reload registers, two parameters: TIMx, NewState TIM_ARRPreloadConfig(TIM4, ENABLE);//Same as above TIM_Cmd(TIM2,ENABLE); //Finally, don't forget to Cmd the peripheral (enable), this is the last step of all peripheral operations TIM_Cmd(TIM4,ENABLE);//Same as above}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
The first two functions are a bit confusing... I have written so many that I don’t even know what they do. Here is a better encapsulated one... written by a senior...
void TIM1_PWM_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //Necessary declaration TIM_OCInitTypeDef TIM_OCInitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11 | GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); TIM_TimeBaseStructure.TIM_Period=19999; TIM_TimeBaseStructure.TIM_Prescaler=71; TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure); TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse=1000; TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; TIM_OC4Init(TIM1,&TIM_OCInitStructure); TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable); TIM_OCInitStructure.TIM_Pulse=2000; TIM_OC1Init(TIM1,&TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable); TIM_CtrlPWMOutputs(TIM1,ENABLE); TIM_ARRPreloadConfig(TIM1,ENABLE); TIM_Cmd(TIM1,ENABLE);}1234567891011121314151617181920212223242526272829303132333435363738
Well, let's simulate it!
Add pins and set thresholds, and you'll see the following analysis window:
Correct!
Previous article:STM32 Cortex system timer (SysTick)
Next article:Configuration process of stm32 serial port
Recommended ReadingLatest update time:2024-11-15 15:29
- Popular Resources
- Popular amplifiers
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- 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)
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
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- Sn-doped CuO nanostructure-based ethanol gas sensor for real-time drunk driving detection in vehicles
- Design considerations for automotive battery wiring harness
- Do you know all the various motors commonly used in automotive electronics?
- Giant Board in crowdfunding
- Blue pipe solution
- If you don't understand this (Martian text), just look at the pictures
- Seeking distance or speed on an RS-485 bus?
- [Small home weather station] Get ESP8266 weather data through UART
- [2022 Digi-Key Innovation Design Competition] 2-DOF Pan-Tilt Robot Control Platform
- 29 electronic engineers stepped on the landmine! See if you are one of them?
- Experience in using Ti's C28x series DSP (28069) (28377D), and inverter state machine
- There are 28 prizes left in the prize pool, first come first served: Mentor helps you design PCB efficiently
- Espressif ESP32-S3-USB-OTG development board information