STM32 study notes (4)丨TIM timer and its application (timing interrupt, internal and external clock source selection)

​ This course uses a single-chip microcomputer model STM32F103C8T6.
​ Course link: STM32 Introductory Tutorial


  Links to past notes:
  STM32 study notes (1) 丨 Building a project 丨 GPIO general input and output
  STM32 study notes (2) 丨 STM32 program debugging 丨 OLED use
  STM32 study notes (3) 丨 Interrupt system 丨 EXTI external interrupt


  If the content of the previous note is an epic dungeon, I would like to call the content of this article a legendary dungeon (1) .


1. TIM timer

1.1 Introduction to TIM Timer

  TIM (Timer) timer, its basic function isCount the input clock and trigger an interrupt when the count value reaches a fixed value, that is, a timing trigger interrupt timer is a counter. When the input of the counter is an accurate and reliable reference clock, the process of counting the reference clock is timing the process of.In STM32, the reference clock of the timer is generally 72MHz .
  The core part of the timer is calledtime base unit, which consists of the following three 16-bit registers:

  • Counter (Counter) : A register used to count the timing. Every time a clock comes, the counter is incremented by 1.
  • Prescaler (Prescaler) : It can divide the clock frequency of the counter to make the clock more flexible.
  • Auto-reload Register : The target value of the count, that is, how many clocks are counted to apply for interrupts.

  Since the registers constituting the time base unit are all 16 bits, if we set the value of the prescaler to the maximum, the automatic reload value is also set to the maximum, and the interrupt frequency is set to f 0 f_0f0, the maximum timing time tmax t_{max} under the main frequency of 72MHztmax,则:
f 0 = 72 / ( 2 16 ) 2 M H z t m a x = 1 f 0 = 59.65 s f_0=72/(2^{16})^2MHz\\ t_{max}=\frac 1 f_0=59.65s f0=72/(216)2M Hz_tmax=f10=59.65 s
  The timing time of 59.65s is already relatively long. If there is a higher time timing requirement,the STM32 timer supports cascading, that is, the input of one timer is the output of another timer, and the timing time at this time is about eight thousand years. If another timer is cascaded, the timing time at this time will reach 34 trillion years. It can be seen that the timing time selection of the STM32 timer is quite free.
  The common functions of STM32 timers are as follows (the listed functions will be covered in this course):

  • Timed interrupt function
  • Internal and external clock source selection
  • input capture
  • output compare
  • Encoder interface
  • master-slave trigger mode

  The timer of STM32 is also designed according to the application scenario and complexity. There are three types of advanced timers, general timers, and basic timers . This course focuses on learning and using general-purpose timers.

1.2 Introduction to TIM timer types and working principles

  The timer type, number and function of STM32 are briefly described in the following table: the
insert image description here
  same chip generally has many timers, and they are all represented by TIMx. Only TIM1~TIM8 are listed in the above table, but there are also TIM9, TIM10, TIM11, etc. in the library functions, which are not commonly used.
  Different timers are connected to different buses. Advanced timers are connected to the higher-performance APB2 bus, while general-purpose timers and basic timers are connected to the APB1 bus. When using RCC to start the timer clock, pay attention to the call of the library function.
  The function of the timer is backward compatible from the high level to the low level. The advanced timer includes all the functions of the general timer, and the general timer includes all the functions of the basic timer. Compared with the general timer, the advanced timer has additional functions, such as repetition counter, dead zone generation, complementary output, brake input, etc. These are designed for the drive of the three-phase brushless motor FOC, which will not be covered in this course.
  The timer resources of the STM32F103C8T6 chip used in this course are: TIM1, TIM2, TIM3, TIM4, which has one advanced timer, three general-purpose timers, and no basic timer. The number and type of timers are different for different chip models. Before using a peripheral, be sure to query whether it exists.

1.2.1 Basic timer working principle and structure

  The basic timer has a timing interrupt, and the master mode triggers the DAC (digital-to-analog converter) function . The block diagram of the basic timer structure is shown in the following figure:
insert image description here
  As can be seen from the above figure, the basic timer has a prescaler PSC (Prescaler), a counter CNT (Counter), and ARR (Auto-reload Register). Basic time base unit. connected before the prescaler isInput of reference clock, since the basic timer can only be connected to the internal clock , it can be directly considered that the clock input CK_PSC of the prescaler is connected to the internal clock CK_INT. The source of the internal clock is RCC_TIMxCLK, and the frequency here is generally the main frequency of the system is 72MHz. So the base clock input of the basic timer can only be 72MHz .
  The PSC prescaler can prescale the reference clock . If the prescaler writes 0, it means no frequency division, or 1 frequency division, then output frequency = input frequency = 72MHz; if the prescaler writes 1, it is 2 frequency division, output frequency = input frequency / 2 = 36MHz; if the prescaler writes 2, it is divided by 3...and so on. So we have the following relationship:
actual frequency division factor = value written by pre-allocator + 1 actual frequency division factor = value written by pre-allocator + 1Actual division factor=the value written by the preallocator+1
  The prescaler is a 16-bit register, so the maximum value can be written into 65535 (2 16 2^{16}216 ), which is 65536 frequency division.
  The CNT counter can count the prescaled count clock CK_CNT. Every time the counting clock CK_CNT has a rising edge, the value of the counter is +1 (it can only be incremented). The counter is also 16-bit, and its value can be 0~65535. If it is +1 again, the counter will return to 0 and start counting again.
  The ARR auto-reload register is the count target of the counter, which is also a 16-bit register. The automatic resetting device is a fixed target during the continuous self-increment of the counter operation. The counter is constantly compared with the reload register. When the count value = the automatic reload value, it means that the timing is up. At this time, the automatic reload register will output an interrupt signal, and the counter will be cleared, and the counter will automatically start the next count timing.
  The upward arrow of the broken line in the figure represents an interrupt signal generated. UI means Update Interrupt, that is,update interrupt, which is an interrupt whose count value is equal to the automatic reload value. The update interrupt will lead to the NVIC, as long as the interrupt channel of the NVIC is configured, the update interrupt of the timer will be responded by the CPU.
  The downward arrow of the broken line in the figure represents an event generated. U here means Update, that is, an update event. The update interrupt does not trigger an interrupt, but it can trigger the operation of other internal circuits. As can be seen in the figure, the auto-reload registers can also respond to events generated by other peripherals.


  A major feature of STM32 is the master-slave trigger mode . It allows the internal hardware to run automatically without the control of the program, that is, to realizehardware automation.
  My understanding here is: the master mode, that is, the mode as the master of the signal, the signal output by the circuit can trigger the response of other circuits in the slave mode. Normally, only one piece of code can be executed at a time to complete one operation. If the master-slave trigger can be used reasonably, "one mind and two tasks" can be realized, which will greatly reduce the CPU operation burden (here is only a simple understanding. , which will be discussed later).
  Take the DAC triggered by the basic timer master mode as an example: when we use the DAC, we may use the DAC to output a waveform, so we need to trigger the DAC every once in a while to let it output the next voltage point. If you follow the interrupt idea, you need to set a timer to generate an interrupt first, and manually trigger a DAC conversion with code in the interrupt program every once in a while, and then the DAC outputs a waveform. There is nothing wrong with this operation, but it will cause the main program to be frequently interrupted, which may affect the running of the main program and the response to other interrupts. Therefore, the main mode of the timer can map the update event U of the timer to the position of the trigger output TRGO (Trigger Out), and then directly connect to the trigger conversion pin of the DAC through TRGO. In this way, the DAC conversion does not need to be triggered by the interrupt generated by the timer. It only needs to map the update event U to TRGO through the main mode, and TRGO can automatically trigger the DAC. This reflects the role of the main mode: the whole process does not require the participation of software, and realizes the automation of hardware .

1.2.2 General timer working principle and structure

  The general-purpose timer has all the functions of the basic timer, and additionally has functions such as internal and external clock source selection, input capture, output comparison, encoder interface, and master-slave trigger mode. The structural block diagram of the general-purpose timer is as follows:
insert image description here

  1. Similarities and differences between general-purpose timers and basic timers

  The most basic structure of a general-purpose timer is also a time base unit, which is the same as the basic timer. It can be considered that the general-purpose timer is obtained by extending many functions on the basis of the basic timer. The difference between it in the time base unit module and the basic timer is: the counting mode of the counter is not only one of counting up . In addition to the same up-counting mode as the basic timer, it also has the following two modes:

  • Down counting mode : counting starts from the reload value, decreases downward, and returns to the reload value after reaching 0, and generates update interrupts and update events at the same time, and so on.
  • Central alignment mode : The count starts from 0 and increases upwards. When the reload value is reached, an update interrupt and an update are generated, and then decreases downward. After the reload value is reached, an update interrupt and an update event are generated, and the cycle is repeated.
  1. Internal and external clock source selection function

  The upper part of the structure diagram is the working structure of internal and external clock source selection and master-slave trigger mode:
insert image description here
  first, let’s look at the working principle of internal and external clock source selection. The basic timer can only choose the internal clock CK_INT from the chip, that is, the system frequency is 72MHz. The general-purpose timer can not only choose the internal clock, but also can choose the external clock. Specifically, there are three types:

  • From the external clock ETR on the TIMx_ETR pin
    insert image description here
      The position of the TIMx_ETR pin can refer to the definition of the default multiplexing function and redefinition function in the pin definition table, as shown in the figure below. It can be seen that both CH1 and ETR of TIM2 are multiplexed on pin PA0. The pins for other timers can also be found in the table.
    insert image description here
      We connect an external square wave clock to the TIMx_ETR pin, and the incoming external clock ETR passes through the internal polarity selection, edge detection and prescaler circuit to generate an external clock pulse ETRP (here I guess P is Pulse, that is, pulse, temporarily No relevant explanation was found ). After passing through the input filter circuit, the subsequent signal is divided into two routes. The above signal ETRF enters the trigger controller (similar to the internal clock process), and then it can be used as the clock input of the time base unit. In STM32, this route is called forExternal Clock Mode 2(as shown by the red line in the figure); the other channel and other signals output TRGI (Trigger In) through a data selector. When this TRGI is used as an external clock, this channel is calledExternal Clock Mode 1(as shown by the yellow line in the figure). From the name of the latter, it is mainly used as a trigger input, which can trigger the slave mode of the timer. The content of the slave mode will be covered later. This section mainly considers the case where this trigger input is considered as an external clock.

  • The signal from other timers.
    Please add a picture description
      The output TRGO of the ITR master mode can lead to other timers, in fact, it leads to the ITR pin. Through this way, the function of cascading timers can be realized. As shown by the yellow line above, ITR0 to ITR3 are respectively from the TRGO outputs of other 4 timers. The specific connection methods are shown in the following table:
    insert image description here

  • TI1_ED from TIMx_CH1 , that is, the clock is obtained from the input capture module connected to the CH1 pin. ED means Edge, which means the clock passing through this path, and both rising and falling edges are valid.

  • TI1FP1 from TIMx_CH1 and TI2FP2 from TIMx_CH2

  To sum up, the input of external clock mode 1 can be ETR pin, other timers, the edge of CH1 pin, CH1 pin and CH2 pin; the input of external clock mode 2 can only be ETR pin.

  1. Encoder interface function

  The encoder interface in the figure, which can read the output model of the quadrature encoder, will be covered in subsequent courses.

  1. Master-slave trigger mode function

  The TRGO in the figure is similar to the basic timer. It can map some events inside the timer to other circuits to complete the functions of other circuits.

  1. output compare function

  The lower right corner of the general-purpose timer structure diagram is the structure of the output comparison function of the timer, as shown in the figure below. There are four output channels, corresponding to the pins of CH1 to CH4, which can be used to output PWM waveforms to drive the motor.
insert image description here

  1. input capture circuit

  The lower left corner of the general-purpose timer is the structure diagram of the input capture circuit, which has four channels like the output comparison function, corresponding to CH1 to CH4. Can be used to measure the frequency of an input square wave. Because the input capture and output comparison cannot be used at the same time, the middle capture/compare register is shared by the input capture and output compare circuits, and the pins from CH1 to CH4 are also shared.
insert image description here

1.2.3 Advanced timer working principle and structure

  Advanced timers have all the functions of general-purpose timers, and additional functions such as repetition counter, dead zone generation, complementary output, and brake input . The block diagram of the advanced timer structure is shown in the figure below:
insert image description here
insert image description here
  Most of the structure of the advanced timer is the same as that of the general timer, and only some functions have been expanded.

  1. Repeat counter

  At the signal output of the interrupt application, a repetition counter is added. Its function is: it can realize that an update event and an interrupt occur only every few counting cycles . It is equivalent to another frequency division of the output update signal .

  1. Dead zone generation circuit and three-phase brushless motor

  The DTG and DTG registers in the figure form a dead zone generation circuit, and the pin TIMx_CH1/CH2/CH3 on the right is changed from one for each channel to two complementary output pins (TIMx_CH1/CH2/CH3 and TIMx_CH1N/CH2N/ CH3N), can output a pair of complementary PWM waves. These circuits are designed to drive three-phase brushless motors. Three-phase brushless motors can be found in quadcopters, electric car rear wheels, and power drills. The driving circuit of the three-phase brushless motor needs three bridge arms, and each bridge arm needs 2 high-power switching tubes to control, and a total of 6 high-power switching tubes are needed for control. Therefore, the first three channels of the output PWM pins become complementary output pins, while the fourth channel TIMx_CH4 remains unchanged.
  In order to prevent the short-term straight-through phenomenon caused by the imperfection of the device at the moment of switch switching when the complementary output PWM drives the bridge arm, a dead zone generating circuit is added . At the moment of switch switching, a certain period of dead zone is generated, so that the upper and lower tubes of the bridge arm are all turned off to prevent the through phenomenon.

  1. brake input

  The main function of the brake input is to provide safety protection for the motor drive . If the external pin BKIN (Break In) generates a brake signal, or the internal clock fails, causing a fault, the control circuit will automatically cut off the output of the motor to prevent accidents.

2. Timing interrupt and internal and external clock source selection

2.1 Basic structure of timed interrupt

  The basic structure of the timer interrupt is shown in the figure below:
Basic structure of timed interrupt
  the core part of the timer is the time base unit. The "operation control" in the figure refers to some bits of the control register, which are used to start or stop the counter, configure the up-down counting mode, etc., and operate these registers to control the operation of the time base unit. The part about the selection of the clock source has been described in detail above, and will not be repeated here.
  After the timing time is up, the generated interrupt signal will first set an interrupt flag bit in the status register, and this flag bit will be controlled by the interrupt output to apply for an interrupt to the NVIC. The reason for the existence of this interrupt output control is that the timer module needs to apply for an interrupt in many places. If the interrupt is needed, the output is allowed; if the interrupt is not needed, the output is disabled. In simple terms, the interrupt output control is the enable bit of the interrupt output.

2.2 Example of running time sequence of time base unit

  In STM32, there are a lot of content about timing operations. For details, please refer to the detailed discussion in the manual. Here are only some examples of time base units for a brief analysis.

2.2.1 Buffer (Shadow) Registers

  At the beginning of the design of STM32, in order to ensure that it can be applied to a variety of situations, the impact of sudden manual changes to the registers on the timing during the timing operation has been carefully designed . The buffer (shadow) register is introduced here. The main purpose is synchronization , that is, the change of some target values ​​set by the register and the update event can occur at the same time, so as to prevent errors caused by changes during operation . In the timer structure diagram, some registers are drawn with shadows under the box, which means that the register is not only one register, but two registers to form a buffer mechanism. In fact,What really changes the state of the sequential circuit is the shadow register .

2.2.2 Prescaler Timing Analysis

insert image description here

Counter counting frequency: CK_CNT = CK_PSC / (PSC + 1)

  The figure above describes the timing diagram of the counter when the division factor of the prescaler is changed from 1 to 2 . When the counter enable signal CNT_EN becomes high level and the next CK_PSC is high level, the timer clock CK_CNT receives CK_PSC. And at this time, the frequency division coefficient of the prescaler is 1, PSC = 0, and the prescaler completes a frequency division, CK_PSC = CK_CNT.
  It can be seen that when the value of the counter register is incremented to 0xFC, it immediately jumps to 0x00, indicating that the target count value of the reload register ARR design is 0xFC. At this time, the circuit generates an update event pulse signal UEV and generates an interrupt signal.
  Write a new value in TIMx_PSC before updating the event signal, and change the frequency division factor of the prescaler from 1 to 2, but due to the existence of the buffer register, CK_CNT will not immediately become CK_PSC / 2, but in the next update When the interrupt is generated, the prescaler buffer (shadow register) modifies the frequency division factor to 2, PSC = 1.
  It can be seen from the timing of the prescaler counter that the frequency division function of the prescaler is actually realized by the counter . When the frequency division factor becomes 2, the prescaler counter counts sequentially according to 0, 1, 0, and 1. Whenever the prescaler counter returns to 0, the prescaler output signal CN_CNT outputs a pulse.

2.2.3 Counter Timing Analysis

  1. Timing diagram of counter operation
    insert image description here

    Counter overflow frequency: CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1)

  2. The counter has no preload timing diagram (buffer mechanism failure APRE = 0).
    insert image description here
      As shown in the figure, when the counter is not preloaded (buffer mechanism), there is another case for changing the value of the TIMx_ARR register: when changing the value of the autoload register, the counter The value of the register is greater than the changed value; however, the value of the counter register can only be incremented at this time, so the register will always increase to the maximum value of 0xFFFF and then return to 0x0000, and then increase in turn until the value of the counter register is the same as that of the ARR register When the value is the same, apply for interruption. It can be seen here that if the buffer mechanism is not used, it may cause some problems to the circuit timing work.
  3. Counters have pre-loaded timings (buffer mechanism active APRE = 1)
    insert image description here

2.2.4 Introduction to RCC clock tree

insert image description here
  RCC clock tree:It is used in STM32 to generate and configure the clock, and transmit the configured peripherals to each peripheral system.The clock is the basis for all peripherals to run, so the clock is the first thing to configure. When the program is executed, a SystemInitfunction will be executed before executing the main program (see: STM32 Study Notes (1) 丨 Establishing a Project 丨 GPIO General Input and Output ). The function of this function is to configure the RCC clock tree.
  The RCC clock tree can be divided into two parts: the clock generation circuit and the clock distribution circuit .

  1. Clock generation circuit
      In the clock generation circuit, there are four oscillation sources, which are the internal 8MHz high-speed RC oscillator, the external 4-16MHz high-speed crystal oscillator (generally connected to 8MHz), and the external 32.768kHz low-speed crystal oscillator (generally Provide clock for RTC), internal 40kHz low-speed RC oscillator (provide clock for watchdog WDG). An external crystal oscillator is more stable than an internal RC oscillator. If the system is very simple and does not require an overly accurate clock, the internal RC oscillator can be used , which can save the external crystal oscillator circuit.
      In SystemInitthe function, the clock is configured as follows: first, the internal 8MHz high-speed RC oscillator will be started to generate the clock, and the clock will be selected as the system clock, which will temporarily run with the 8MHz internal clock ; then the external clock will be started, and the external clock signal will flow through The circuit shown in the figure below:
    Please add a picture description
    the external crystal oscillator signal enters the PLLMUL phase-locked loop for frequency multiplication, and the frequency of 8MHz is multiplied by 9 times to obtain 72MHz. After the output of the phase-locked loop is stable, select the output of the phase-locked loop as the system clock. This switches the system clock from 8MHz to 72MHz. This analysis can draw a conclusion: if there is a problem with the external crystal oscillator, the program clock may be about 10 times slower . If there is a problem with the hardware circuit of the external clock (the crystal oscillator is short-circuited or connected incorrectly, etc.), the system clock cannot be switched to 72MHz, and the internal 8MHz will remain running.
      The CSS in the figure is called the clock security system, which is also responsible for switching the clock. CSS can detect the running status of the clock. Once the external clock fails, it will automatically switch the external clock to the internal clock , so as to ensure that the program can run normally and will not cause accidents due to stuck. In addition, in the brake input function of the advanced timer, CSS is also responsible for detecting when the external clock fails, and immediately cuts off the output control pin and cuts off the motor output to prevent accidents.
  2. The middle
      signal SYSCLK (72MHz) generated by the clock distribution circuit clock generation circuit first enters the AHB bus. There is a prescaler on the AHB bus. The SystemInitdefault frequency division factor in the function configuration is 1, so the clock of the A HB bus is naturally 72MHz .
      After that, the signal enters the APB1 bus, and there is also a prescaler on APB1. The SystemInitdefault frequency division factor configured here is 2, and the output is 36MHz, so the clock of the APB1 bus is 36MHz . The general-purpose timer and the basic timer are connected to APB1, but the connection timer of APB1 (APB2 is the same) has the following structure as shown in the figure: the
    insert image description here
    general-purpose timer and the basic timer connect with APB1 through the branch below APB1 in the figure connect. Since the prescaler coefficient of APB1 is 2 by default, the clock frequency output to the timer is ×2. The frequency division coefficient of the prescaler of APB2 is configured as 1 by default, and other processes are the same as APB1. Therefore, the internal reference clocks of basic timers, general-purpose timers, and advanced timers are all 72MHz . This design brings convenience for us to use timers, and we don’t need to consider the different clocks of different timers ( the premise is not to modify SystemInitthe function indiscriminately. default configuration ).
      At the clock output port, there is an AND gate for clock output control. The external clock enableRCC_APB2/1PeriphClockCmd of the control terminal is where the function works in the program .

2.3 Timing interrupt and clock source selection related library function usage

  There are many timer-related library functions, this section only discusses the library functions to be used andSome usage detailsTo illustrate ( and even that is a lot ).

  1. Timer initialization configuration
  • Time base unit configuration function
// 恢复定时器缺省配置
void TIM_DeInit(TIM_TypeDef* TIMx);

// 时基单元初始化
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

// 把时基单元初始化函数所用的结构体变量赋一个默认值
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

// 使能计数器(对应定时中断结构图中的“运行控制”功能) 
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

// 使能中断输出信号(对应定时中断结构图中的“中断输出控制”功能)
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
  • Clock source selection configuration function of time base unit
// 时基单元的时钟选择相关函数
// 选择内部时钟
TIM_InternalClockConfig(TIM_TypeDef* TIMx);

// 选择ITRx其他定时器的时钟,TIM_InputTriggerSource为选择要接入哪个定时器
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);

// 选择TIx捕获通道的时钟,TIM_InputTriggerSource为选择的引脚,TIM_ICPolarity为输入极性选择,ICFilter为滤波配置
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
                                uint16_t TIM_ICPolarity, uint16_t ICFilter);

// 选择ETR外部时钟模式1输入的时钟,TIM_ExtTRGPrescaler为ETR外部时钟预分频器,TIM_ExtTRGPolarity为输入极性选择,ExtTRGFilter为滤波配置
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                             uint16_t ExtTRGFilter);

// 选择ETR外部时钟模式1输入的时钟,参数与上一个函数完全相同,且对于ETR外部时钟输入而言,两个函数等效,如果不需要触发输入的功能,则两个函数可以互换
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, 
                             uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);

// 单独配置ETR外部引脚的预分频器,极性,滤波参数
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                   uint16_t ExtTRGFilter);
  1. Parameter (PSC, ARR, etc.) change function ( modified during program running )
// 预分频值设置,TIM_PSCReloadMode为是否应用输入缓冲功能配置
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);

// 改变计数器的计数模式
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);

// 自动重装寄存器预装功能配置(计数器有无预装功能)
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

// 手动给计数器写入一个值
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);

// 手动给自动重装寄存器写入一个值
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);

// 获取当前计数器的值
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);

// 获取当前的预分频器的值
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);

// 获取定时中断的标志位和清除标志位,使用方法与EXTI相同
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
  1. Some details of using timer library functions
  • Select the internal clock function : after the timer is powered on, the internal clock is selected by default. If you want to select the internal clock, this sentence can be omitted.

    TIM_InternalClockConfig(TIM_TypeDef* TIMx);
    
  • Time base unit initialization functionTIN_TimeBaseInit : When configuring structure variables, you will encounter the following details

  1. TIM_TimeBaseInitStructure.TIM_ClockDivision(Sampling) Clock frequency division frequency selection
      There is generally a filter on the external signal input pin of the timer to eliminate the jitter interference of the signal. Its working principle is:at a fixed clock frequency ffSampling under f , if continuous NNThe N sampling points are all at the same level, which means that the input signal is stable, and the sampling value is output to the next stage circuit; ifNNIf the N sampling points are not all the same, it means that the signal has jitter. At this time, keep the last output, or directly output low level.This ensures that the output signal is filtered to a certain extent. Here the sampling frequency fff and the number of sampling pointsNNN is the parameter of the filter, the lower the frequency, the more sampling points, the better the filtering effect, but the corresponding signal delay is greater.
      Sampling frequency fThe source of f can be directly provided by the internal clock, or it can be obtained by adding a clock frequency division to the internal clock.The frequency division is TIM_ClockDivisiondetermined by the parameters. It can be seen TIM_ClockDivisionthat the relationship with the time base unit is not great , and its optional value can be 1 frequency division, 2 frequency division and 4 frequency division.
  2. When configuring the structure variable, there is no parameter that can directly operate the counter CNT. If desired, SetCounterthe and GetCountertwo functions can be used to manipulate the counter.
  3. TIM_TimeBaseInitStructure.TIM_RepetitionCounterRepeat count register, through this parameter you can set the repeat count register. However, there is no such register in the general-purpose timer, so it can be directly set to 0.
  4. Calculation reference formula for timing time
      :Counter overflow frequency: CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1), Note that the values ​​of PSC ( TIM_Prescaler) and ARR ( TIM_Period) must be between 0 and 65535.
  5. At TIM_TimeBaseInitthe end of the function, theImmediately generate an update event, to reload the prescaler and repeat counter values. The prescaler has buffer registers, and the PSC and ARR we write to will only work on update events. However, the update event and the update interrupt occur at the same time. The update interrupt will set the update interrupt flag. Manually generating an update event is equivalent to entering the update function to execute once during initialization.Manually clear the update interrupt flag bit before enabling the interrupt, which can avoid the problem of entering the interrupt function just after the initialization is completed.
  • External clock configuration functionTIM_ETRClockMode2Config
  1. TIM_ExtTRGPrescalerExternal clock prescaler : You can choose external clock frequency division off (1 frequency division), 2 frequency division, 4 frequency division, and 8 frequency division.
  2. TIM_ExtTRGPolarityThe polarity of the external trigger : TIM_ExtTRGPolarity_Invertedreverse polarity, that is, low level and falling edge are valid; TIM_ExtTRGPolarity_NonInvertednon-reverse, that is, high level and rising edge are valid.
  3. ExtTRGFilterExternal input filter : The working principle is similar to the filter of the internal clock, and its value can be a value between 0x00 and 0x0F, which determines the sampling fff andNNN , the specific corresponding relationship has a corresponding table in the manual:
    insert image description here
  4. GPIO configuration : Because the external interface is used to input the clock, the GPIO port needs to be configured before using this function. For the timer, the recommended configuration given in the manual isfloating input. However, the floating input will cause the input level of the pin to be easily disturbed, so the power of the input signal is not small, and the pull-up or pull-down input is generally selected.When the power of the external input signal is very small, the internal pull-up/pull-down resistor (larger) may affect the input signal. At this time, it is necessary to use a floating input to prevent the external input level from being affected.
    insert image description here

2.4 Example of Timer Timing Interrupt

  The phenomenon to be completed in this experiment is: define a uint16_t Num variable to make it +1 per second. The device connection diagram and program source code are as follows:
insert image description here

  • Timer.c
#include "stm32f10x.h"                  // Device header

// 用extern声明变量后,这里的Num就会成为main.c文件中Num的引用
extern uint16_t Num;

void Timer_Init(void)
{
    
    
	// 用RCC外设时钟控制打开定时器的基准时钟和外设的工作时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	// 选择时基单元的时钟源(这里使用内部时钟)
	// 定时器上电后默认使用内部时钟,如果使用内部时钟这一步也可以省略
	TIM_InternalClockConfig(TIM2);
	
	// 配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;	// 配置时钟分频频率(用于采样滤波,在这里它的取值不重要,取哪一个都可以)
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;	// 配置计数模式
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;	// 周期,即自动重装寄存器的值ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;	// 预分频系数PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;	// 重复计数寄存器,高级定时器才有的模块,这里配置为0
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	// 在TIM_TimeBaseInit函数的最后,会立刻生成一个更新事件,来重新装载预分频器和重复计数器的值
	// 预分频器有缓冲寄存器,我们写入的PSC和ARR只有在更新事件时才会起作用
	// 为了让写入的值立刻起作用,故在函数的最后手动生成了一个更新事件
	// 但是更新事件和更新中断是同时发生的,更新中断会置更新中断标志位,手动生成一个更新事件,就相当于在初始化时立刻进入更新函数执行一次
	// 在开启中断之前手动清除一次更新中断标志位,就可以避免刚初始化完成就进入中断函数的问题
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	
	// 配置中断输出控制,允许中断输出到NVIC
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	// 配置NVIC,在NVIC中打开定时器中断的通道,并分配优先级
	// NVIC通道优先级分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	// 初始化NVIC
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;	// 配置NVIC中断通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	// 中断通道命令
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;	// 响应优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;	// 抢占优先级
	NVIC_Init(&NVIC_InitStructure);
	
	// 配置运行控制
	TIM_Cmd(TIM2, ENABLE);
}

void TIM2_IRQHandler(void)
{
    
    
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{
    
    
		Num ++;
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}

  • main.c
#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Timer.h"

uint16_t Num;

int main()
{
    
    
	OLED_Init();
	Timer_Init();
	OLED_ShowString(1, 1, "Num:");	// 显示一个字符串

	while(1)
	{
    
    
		OLED_ShowNum(1, 5, Num, 5);
		// OLED_ShowNum(2, 5, TIM_GetCounter(TIM2), 5);
	}
}

2.5 Timer external clock selection

  The phenomenon to be completed in this experiment is: use a photosensitive sensor to manually simulate an external clock, define a uint16_t Num variable, and when the external clock triggers 10 times (pulse after prescaler), Num + 1. The device connection diagram and program source code are as follows:
insert image description here

  • Timer.c
#include "stm32f10x.h"                  // Device header

// 用extern声明变量后,这里的Num就会成为main.c文件中Num的引用
extern uint16_t Num;

void Timer_Init(void)
{
    
    
	// 用RCC外设时钟控制打开定时器的基准时钟和外设的工作时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	// RCC打开GPIO的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 选择时基单元的时钟源(使用ETR外部时钟)
	TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);
	
	// 配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;	// 配置时钟分频频率(用于采样滤波,在这里它的取值不重要,取哪一个都可以)
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;	// 配置计数模式
	TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;	// 周期,即自动重装寄存器的值ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 2 - 1;	// 预分频系数PSC(这里如果PSC设置为0,会连续触发中断,导致主程序不运行,是我的芯片Bug问题)
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;	// 重复计数寄存器,高级定时器才有的模块,这里配置为0
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	// 在TIM_TimeBaseInit函数的最后,会立刻生成一个更新事件,来重新装载预分频器和重复计数器的值
	// 预分频器有缓冲寄存器,我们写入的PSC和ARR只有在更新事件时才会起作用
	// 为了让写入的值立刻起作用,故在函数的最后手动生成了一个更新事件
	// 但是更新事件和更新中断是同时发生的,更新中断会置更新中断标志位,手动生成一个更新事件,就相当于在初始化时立刻进入更新函数执行一次
	// 在开启中断之前手动清除一次更新中断标志位,就可以避免刚初始化完成就进入中断函数的问题
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	
	// 配置中断输出控制,允许中断输出到NVIC
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	// 配置NVIC,在NVIC中打开定时器中断的通道,并分配优先级
	// NVIC通道优先级分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	// 初始化NVIC
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;	// 配置NVIC中断通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	// 中断通道命令
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;	// 响应优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;	// 抢占优先级
	NVIC_Init(&NVIC_InitStructure);
	                     
	// 配置运行控制
	TIM_Cmd(TIM2, ENABLE);
}

uint16_t Timer_GetCounter(void)
{
    
    
	return TIM_GetCounter(TIM2);
}

void TIM2_IRQHandler(void)
{
    
    
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{
    
    
		Num ++;
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}

  • main.c
#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Timer.h"

uint16_t Num;

int main()
{
    
    
	OLED_Init();
	Timer_Init();
	OLED_ShowString(1, 1, "Num:");	// 显示一个字符串
	OLED_ShowString(2, 1, "CNT:");
	
	while(1)
	{
    
    
		OLED_ShowNum(1, 5, Num, 5);
		OLED_ShowNum(2, 5, Timer_GetCounter(), 5);
	}
}


  Next: STM32 study notes (5)丨TIM timer and its application (output comparison丨PWM driving breathing lamp, steering gear, DC motor)


  Original notes, code words are not easy, welcome to like, bookmark~ If there is any error, please let me know in the comment area, thank you very much! The blogger will continue to update study notes about embedded development and machine learning~

Guess you like

Origin blog.csdn.net/weixin_62179882/article/details/128462610