I’m back to write study notes again.
Previously, I wrote a summary of some new terms related to STM32, and at that time, I had just learned about timers. Now that I have finished learning about timers, I suddenly wanted to summarize the usage of timers, which led to the birth of this blog.
The materials mentioned in the article are from Jiangxie videos:
https://www.bilibili.com/video/BV1th411z7sn/?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click&vd_source=e836ee461d07a48f2161731d0ca031f0
(1) Timer Interrupt#
A timer interrupt, as the name suggests, is triggered by counting through the timer.
First, enable the clock using the RCC_APB1PeriphClockCmd function (you must enable the clock before doing anything). If using external pins, remember to enable the clock with the RCC_APB2PeriphClockCmd function and initialize the pins with GPIO_Init.
There are four modes for the timer: internal clock mode, external clock mode 1 and 2, and encoder mode. To configure the timer interrupt, we need to choose one from these four modes. The difference between external interrupt mode 1 and 2 is that mode 2 is an event interrupt, which does not interrupt the normal operation of the program.
The function to configure the internal clock is TIM_InternalClockConfig, and the only parameter needed is the name of the timer.
The function to configure external clock mode 2 is TIM_ETRClockMode2Config, which requires the timer name, timer prescaler, counting method (high-level counting or low-level), and filtering.
The function to configure external clock mode 1 is TIM_ETRClockMode1Config; I haven't used this one, and the information found online is vague, so I won't discuss it.
The function to configure the capture channel is TIM_ICInit, which requires the timer name and the address of the input capture structure, which will be discussed later.
The Jiang University video taught the usage of internal clock mode and external clock mode 2.
Next, we configure the time base unit using the function TIM_TimeBaseInit, which requires the timer name and the address of the time base unit structure as parameters.
The time base unit structure mainly includes prescaler, counting method (usually counting up), ARR, and PSC register values (these two are the counting period and prescaler), and there is a repetition counter, but we are learning about general timers, which do not have this function.
Then we use TIM_ITConfig to enable the interrupt. Before that, we need to use TIM_ClearFlag(TIMx, TIM_FLAG_Update) to clear the update flag because the TIM_TimeBaseInit function manually generates an update event at the end. If this flag is not cleared, the interrupt will immediately trigger once after enabling it.
Finally, we configure NVIC using NVIC_PriorityGroupConfig and NVIC_Init to configure the interrupt order, and then use TIM_Cmd to enable the timer.
(2) Output Compare#
Output compare is essentially outputting a PWM wave (to put it bluntly), with many mode options, but generally, PWM mode 1 or 2 is used directly.
First, as before, enable the clock using the RCC_APB1PeriphClockCmd function, and remember to enable the clock with the RCC_APB2PeriphClockCmd function and initialize the pins with GPIO_Init.
Then use TIM_InternalClockConfig to configure the internal clock (actually not necessary, as it defaults to internal clock).
Next, configure the time base unit, just like before.
Then we need to use TIM_OC1Init to configure the output compare function for channel one. It is mentioned that there are a total of four output compare channels, each connected to specific pins, so you need to refer to the pin definition diagram to choose. The parameters required for this function include the timer name and the output compare structure, which includes the configured mode (just select PWM1), output polarity, and the value of CCR, which is the output compare register that compares with the counter CNT to output high and low levels.
Finally, use TIM_Cmd to enable the timer.
It is also worth mentioning the TIM_SetCompare1 function, which is used to change the value of CCR.
(3) Input Capture#
Input capture is used to capture the high and low levels in the current to calculate the input frequency using the timer.
The first two steps are the same as before: enable the clock and configure the time base unit, but here we need to set ARR to the maximum to prevent the counter from overflowing, so it should be set to 65535.
Then we call TIM_ICInit to configure the input capture mode (for PWMI mode, use TIM_PWMIConfig). The required parameters include the channel (there are four channels, just like output compare, each corresponding to different pins, so you need to refer to the pin definition diagram to choose), filtering, input polarity, prescaler, and signal crossing (this will be used in PWMI mode, generally just select direct connection).
Next, use TIM_SelectInputTrigger and TIM_SelectSlaveMode to select the trigger source and slave mode.
In the trigger source, TI1FP1 and TI1FP2 represent channel one and two, respectively (by the way, I didn't see channel three and four). The slave mode is selected as reset (Reset), meaning that when TI1 generates a rising edge, it will trigger CNT to reset to zero.
Finally, use TIM_Cmd to enable the timer.
Other functions worth mentioning are TIM_GetCapture1 and TIM_GetCapture2, which read CRR1 and CRR2. In normal mode, both represent the captured frequency, while in PWMI mode, CRR1 represents the captured frequency, and CRR2 represents the low-level frequency, with CRR2/CRR1 being the duty cycle.
(4) Encoder Mode#
Encoder mode is specifically used to measure the output frequency of encoders and can only use channels one and two.
Configuring encoder mode is similar to configuring input capture, except that encoder mode requires two pins, and the capture channels also need to be configured with TIM_ICInit for both.
Next, use TIM_EncoderInterfaceConfig to configure the encoder mode, which requires parameters such as the timer name, where to count (select TI12, not sure what the other two settings are for), and the two polarities (here, polarity means whether to reverse; if you feel the counting direction of the encoder needs to be changed, just change one of the polarities).
Finally, use TIM_Cmd to enable the timer.
We can use the TIM_GetCounter function to read the value of the encoder.
So that's all for the timer usage we've learned. Before writing the blog, I thought I had understood it quite well, but when I actually started writing, I realized my understanding was still too superficial, and I wrote it very hurriedly. I'm not sure if there are any mistakes.