STM32 has a total of 8 timers:
Timer Type | Number of digits | model | Special application scenarios |
---|---|---|---|
Advanced timer TIME1, TIME8 | 16-bit | Up, Down, Up/Down | PWM click control |
General timer TIME2~TIME5 | 16-bit | Up, Down, Up/Down | Timing counting, PWM output, input capture, output comparison |
Basic timer TIME6, TIME7 | 16-bit | Up, Down, Up/Down | Driving the DAC |
General timer functions:
Located on the low-speed APB1 bus (APB1)
16-bit up, down, up/down (center-aligned) counting modes, auto-reload counter (TIMx_CNT).
16-bit programmable (can be modified in real time) prescaler (TIMx_PSC) to divide the counter clock.
4 independent channels (TIMx_CH1~4), these channels can be used as: input capture, output comparison, PWM generation (edge or center alignment mode), single pulse mode output.
You can use external signals (TIMx_ETR) to control the synchronization circuits of timers and timer interconnections (one timer can be used to control another timer).
Generate interrupts/DMA on the following events (6 independent IRQ/DMA request generators): Update: counter overflow/underflow, counter initialization (by software or internal/external trigger), trigger event (counter start, stop, initialize or count by internal/external trigger), input capture, output compare, etc.
General timer clock CK_INT = 2 * 36M = 72M
up counting mode: the counter counts from 0 to the automatic reload value (TIMx_ARR), then restarts counting from 0 and generates a counter overflow event.
Program requirements:
Through the timer interrupt configuration, interrupt once every 500ms, and then control the LED in the interrupt service function to achieve LED1 state inversion (flashing).
Tout (overflow time) = (ARR+1)(PSC+1)/Tclk
timer.c
#include "timer.h" #include "led.h" //General timer 3 interrupt initialization //Here the clock is selected to be twice that of APB1, and APB1 is 36M //arr: automatic reload value. //psc: clock pre-division number //Here timer 3 is used! void TIM3_Int_Init(u16 arr,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //Clock enable //Timer TIM3 initialization TIM_TimeBaseStructure.TIM_Period = arr; //Set the value of the auto-reload register period to load the activity at the next update event TIM_TimeBaseStructure.TIM_Prescaler =psc; //Set the prescaler value used as the TIMx clock frequency divisor TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //Set clock division: TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM up counting mode TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //Initialize the time base unit of TIMx according to the specified parameters TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //Enable the specified TIM3 interrupt and allow update interrupt //Interrupt priority NVIC setting NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3 interrupt NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //Preemption priority level 0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //From priority level 3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ channel is enabled NVIC_Init(&NVIC_InitStructure); //Initialize NVIC registers TIM_Cmd(TIM3, ENABLE); //Enable TIMx} //Timer 3 interrupt service routine void TIM3_IRQHandler(void) //TIM3 interrupt { if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //Check whether TIM3 update interrupt occurs { TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //Clear TIMx update interrupt flag LED1=!LED1; } }12345678910111213141516171819202122232425262728293031323334353637
PWM Output
work process:
CCR1: Capture compare (value) register (x=1,2,3,4): Set the compare value.
CCMR1: OC1M[2:0] bit:
For PWM mode, used to set PWM mode 1 [110] or PWM mode 2 [111]
Mode 1: The count value is less than the CCR1 value, which is the valid level
Mode 2: The count value is greater than the CCR1 value, which is the valid level
CCER: CC1P bit: Input/capture 1 output polarity. 0: High level is valid, 1: Low level is valid.
CCER: CC1E bit: Input/capture 1 output enable. 0: Off, 1: On.
PWM output configuration steps:
1. Enable timer 3 and related IO port clocks.
Enable timer 3 clock: RCC_APB1PeriphClockCmd();
Enable GPIOB clock: RCC_APB2PeriphClockCmd();
2. Initialize the IO port as multiplexed function output. Function: GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
3. Here we want to use PB5 as the PWM output pin of the timer, so we need to remap the configuration.
So you need to turn on the AFIO clock. Also set the remapping.
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
4. Initialize timer: ARR, PSC, etc.: TIM_TimeBaseInit();
5. Initialize output comparison parameters: TIM_OC2Init();
6. Enable preload register:
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
7. Enable the timer. TIM_Cmd();
8. Continuously change the comparison value CCRx to achieve different duty cycle effects: TIM_SetCompare2();
Program Requirements:
Use the PWM function of timer 3 to output a PWM wave with a variable duty cycle to drive the LED light, so that the brightness of LED [PB5] changes from dark to bright, and then from bright to dark, and so on.
timer.c
void TIM3_PWM_Init(u16 arr,u16 psc) { //Define structure variables GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //Enable timer 3 clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //Enable GPIO clock and AFIO multiplexing function module clock GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3 partial remap TIM3_CH2->PB5 //GPIO initialization, set the pin to multiplex output function, output TIM3 CH2 PWM pulse waveform GPIOB.5 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); //Initialize TIM3 TIM_TimeBaseStructure.TIM_Period = arr; //Set the value of the auto-reload register period to load the activity at the next update event TIM_TimeBaseStructure.TIM_Prescaler =psc; //Set the prescaler value used as the TIMx clock frequency divisor TIM_TimeBaseStructure.TIM_ClockDivision = 0; //Set clock division: TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM up counting mode TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //Initialize the time base unit of TIMx according to the parameters specified in TIM_TimeBaseInitStruct //Initialize TIM3 Channel2 PWM mode TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //Set PWM mode 2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //Comparison output enable TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //High level is valid TIM_OC2Init(TIM3, &TIM_OCInitStructure); //Initialize peripheral TIM3 OC2 according to the parameters specified by T TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //Enable TIM3 preload register on CCR2 TIM_Cmd(TIM3, ENABLE); //Enable TIM3}123456789101112131415161718192021222324252627282930
main.c
int main(void) { u16 led0pwmval=0; u8 dir=1; delay_init(); //delay function initialization NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //Set NVIC interrupt group 2: 2-bit preemption priority, 2-bit response priority uart_init(115200); //Serial port initialized to 115200 LED_Init(); //LED port initialization TIM3_PWM_Init(899,0); //No frequency division. PWM frequency = 72000000/900 = 80Khz while(1) { delay_ms(10); if(dir)led0pwmval++; else led0pwmval--; if(led0pwmval>300)dir=0; if(led0pwmval==0)dir=1; TIM_SetCompare2(TIM3,led0pwmval); //Set duty cycle } }12345678910111213141516171819
Input capture:
General configuration steps for input capture:
① Initialize the timer and the clock of the channel corresponding to the IO.
② Initialize the IO port, the mode is input: GPIO_Init();
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPD; //PA0 input
③ Initialize timer ARR, PSC
TIM_TimeBaseInit();
④Initialize input capture channel
TIM_ICInit();
⑤If you want to enable capture interrupt,
TIM_ITConfig();
NVIC_Init();
⑥ Enable timer: TIM_Cmd();
⑦Write interrupt service function: TIMx_IRQHandler();
Experimental purpose: measure the pulse width of the signal
//Timer 5 channel 1 input capture configuration TIM_ICInitTypeDef TIM5_ICInitStructure; void TIM5_Cap_Init(u16 arr,u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //Enable TIM5 clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //Enable GPIOA clock GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0 clears the previous settings GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 input GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0 pull down //Initialize timer 5 TIM5 TIM_TimeBaseStructure.TIM_Period = arr; //Set the counter to automatically reload value TIM_TimeBaseStructure.TIM_Prescaler =psc; //Prescaler TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //Set clock division: TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM up counting mode TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); //Initialize the time base unit of TIMx according to the parameters specified in TIM_TimeBaseInitStruct //Initialize TIM5 input capture parameters TIM5_ICInitStructure.TIM_Channel = TIM_Channel_1; //CC1S=01 Select input IC1 to map to TI1 TIM5_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //Rising edge capture TIM5_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //Map to TI1 TIM5_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //Configure input frequency division, no frequency division TIM5_ICInitStructure.TIM_ICFilter = 0x00; //IC1F=0000 Configure input filter No filtering TIM_ICInit(TIM5, &TIM5_ICInitStructure); //Interrupt group initialization NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; //TIM3 interrupt NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //Preemption priority level 2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //From priority level 0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ channel is enabled NVIC_Init(&NVIC_InitStructure); //Initialize peripheral NVIC registers according to the parameters specified in NVIC_InitStruct TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE); //Enable update interrupt, allow CC1IE to capture interrupt TIM_Cmd(TIM5,ENABLE ); //Enable timer 5}u8 TIM5CH1_CAPTURE_STA=0; //Input capture status u16TIM5CH1_CAPTURE_VAL; //Input capture value //Timer 5 interrupt service routine void TIM5_IRQHandler(void) { if((TIM5CH1_CAPTURE_STA&0X80)==0)//Not captured successfully { if (TIM_GetITStatus(TIM5, TIM_IT_Update) != RESET) { if(TIM5CH1_CAPTURE_STA&0X40)//High level has been captured { if((TIM5CH1_CAPTURE_STA&0X3F)==0X3F)//The high level is too long { TIM5CH1_CAPTURE_STA|=0X80; //Marks a successful capture TIM5CH1_CAPTURE_VAL=0XFFFF; } else TIM5CH1_CAPTURE_STA++; } } if (TIM_GetITStatus(TIM5, TIM_IT_CC1) != RESET) //Capture 1 capture event occurs { if(TIM5CH1_CAPTURE_STA&0X40) //Capture a falling edge { TIM5CH1_CAPTURE_STA|=0X80; //Marks a successful capture of a high level pulse width TIM5CH1_CAPTURE_VAL=TIM_GetCapture1(TIM5); TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising); //CC1P=0 set to rising edge capture }else //Not started yet, first capture rising edge { TIM5CH1_CAPTURE_STA=0; //Clear TIM5CH1_CAPTURE_VAL=0; TIM_SetCounter(TIM5,0); TIM5CH1_CAPTURE_STA|=0X40; //Marker captures the rising edge TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Falling); //CC1P=1 set to falling edge capture } } } TIM_ClearITPendingBit(TIM5, TIM_IT_CC1|TIM_IT_Update); //Clear interrupt flag bit} main.cextern u8 TIM5CH1_CAPTURE_STA; // Input capture status extern u16TIM5CH1_CAPTURE_VAL; // Input capture value int main(void) { u32 temp=0; delay_init(); //delay function initialization NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //Set NVIC interrupt group 2: 2-bit preemption priority, 2-bit response priority uart_init(115200); //Serial port initialized to 115200 LED_Init(); //LED port initialization TIM3_PWM_Init(899,0); //No frequency division. PWM frequency = 72000/(899+1) = 80Khz TIM5_Cap_Init(0XFFFF,72-1); //Count at 1Mhz frequency while(1) { delay_ms(10); TIM_SetCompare2(TIM3,TIM_GetCapture2(TIM3)+1); if(TIM_GetCapture2(TIM3)==300) TIM_SetCompare2(TIM3,0); if(TIM5CH1_CAPTURE_STA&0X80)//Successfully captured a rising edge { temp=TIM5CH1_CAPTURE_STA&0X3F; temp*=65536; //Total overflow time temp+=TIM5CH1_CAPTURE_VAL; //get the total high level time printf("HIGH:%d us\r\n",temp);//Print the total high point flat time TIM5CH1_CAPTURE_STA=0; //Start the next capture } } }
Previous article:STM32 Series Chapter 12 - Principle of Capacitive Touch Button
Next article:STM32 Series Part 10 - Watchdog
Recommended ReadingLatest update time:2024-11-16 13:05
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Communication failure
- Pirated copies are really hard on the eyes - do you feel the same?
- New Year's treasure hunt, Tektronix gives you benefits! Come and start your treasure hunt! The event has begun~
- How to achieve multi-point control of field effect tube electronic switches
- Extremely smooth OLED scrolling display
- What? Microsoft deliberately lets you install pirated software!
- [Perf-V Evaluation] + Construction of Hummingbird Development Environment
- Please help me find a voltage regulator diode. The requirement is 0.5W 4.7V. When the input voltage is 4.5V, the leakage current should be less than 0.2mA.
- Studying the Road to Electric Motor Drive-9: Calculation of “Torque”
- 【Warehouse temperature and humidity automatic control simulation system】- Work submission