Timer classification
stm32f1 series, 8 timers, basic timer (TIM6,7), general timer (TIM2,3,4,5) and advanced timer (TIM1,8).
Basic timer: a 16 bit timer that can only count up. It can only be timed without external IO
General timer: 16 bit timer that can count up / down, timing, output comparison and input capture. Each timer has 4 external IO
Advanced timer: 16 bit timer that can count up / down. It can timing, output comparison, input capture and complementary output signals of three-phase motor. Each timer has 8 external IO's
Functional block diagram of basic timer
Clock source: timer clock TIMxCLK, i.e. internal clock CK_INT is provided by APB1 prescaler.
APB1 prescaler coefficient is equal to 1, and the frequency remains unchanged.
The coefficient of APB1 prescaled in the library function is 2, that is, PCLK1=36M, so the timer clock TIMxCLK=36*2=72M.
Counter clock CK_CNT:
After the timer clock passes through the PSC prescaler, it is CK_CNT, used to drive counter counting.
PSC is a 16 bit prescaler, which can divide the timer clock timxclk by any number between 1 and 65536. CK_CNT=TIMxCLK/(PSC+1).
Counter CNT:
CNT is a 16 bit counter, which can only count up, and the maximum count value is 65535. When the count reaches the automatic reload register, an update event is generated and cleared to start counting from scratch.
Automatic reload register ARR:
16 bit register, which contains the maximum value that the counter can count. When the count reaches this value, if the interrupt is enabled, the timer will generate an overflow interrupt.
Timing time:
The timing time of the timer is equal to the interrupt period of the counter multiplied by the number of interrupts.
Counter in CK_ Driven by CNT, count the time of a number, 1 / (TIMxCLK/(PSC+1)) = 1/(CK_CNT)
Time to generate an interrupt: 1/CK_CNT * ARR
Set a variable time in the interrupt service program to record the number of interrupts. The timing time can be calculated
timer initiated
typedef struct { uint16_t TIM_Prescaler; /*Prescaler. The clock source is the timer clock through the prescaler, which sets timx_ The value of the PSC register. It can be set from 0 to 65535 to achieve frequency division from 1 to 65536 */ uint16_t TIM_CounterMode; /*In the counting mode, the basic timer can only count up, TIMx_CNT can only be incremented from 0 and does not need to be initialized. */ uint16_t TIM_Period; /*Timer cycle, set the value of the automatic reload register and update it to when the event is generated Shadow register. The settable range is 0 to 65535. */ uint16_t TIM_ClockDivision; /*Clock frequency division, set timer clock CK_INT frequency and digital filter sampling clock Frequency division ratio, the basic timer does not have this function and does not need to be set*/ uint8_t TIM_RepetitionCounter; /*The repeater belongs to the special register bit of the advanced control register, which can be used to To control the number of output PWM. The basic timer does not need to be set */ } TIM_TimeBaseInitTypeDef;
experiment
Use the basic timer TIM6/7 to time 1s, and the LED will flip once in 1s.
#define BASIC_ TIM_ Period 1000-1 / / timer cycle, set the value of auto reload register #define BASIC_ TIM_ / / the prescaler is the prescaler
Set the value of the automatic reload register ARR to 1000, set the clock prescaler to 71, and drive the clock of the counter: CK_CNT = CK_INT / (71+1)=1M
Counter count time: 1/CK_CNT=1us.
When the counter counts to ARR=1000, an interrupt is generated. The time of one interruption is: 1/CK_CNT*ARR=1ms
#ifndef __BSP_TIMEBASE_H #define __BSP_TIMEBASE_H #include "stm32f10x.h" /********************Basic timer TIM parameter definition, only TIM6 and 7************/ #define BASIC_TIM6 / / if you use TIM7, just comment out this macro #ifdef BASIC_TIM6 / / use basic timer TIM6 #define BASIC_TIM TIM6 #define BASIC_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd #define BASIC_TIM_CLK RCC_APB1Periph_TIM6 #define BASIC_TIM_Period 1000-1 #define BASIC_TIM_Prescaler 71 #define BASIC_TIM_IRQ TIM6_IRQn #define BASIC_TIM_IRQHandler TIM6_IRQHandler #else / / use basic timer TIM7 #define BASIC_TIM TIM7 #define BASIC_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd #define BASIC_TIM_CLK RCC_APB1Periph_TIM7 #define BASIC_TIM_Period 1000-1 #define BASIC_TIM_Prescaler 71 #define BASIC_TIM_IRQ TIM7_IRQn #define BASIC_TIM_IRQHandler TIM7_IRQHandler #endif /**************************Function declaration********************************/ void BASIC_TIM_Init(void); #endif /* __BSP_TIMEBASE_H */
Define a global variable time. Each time an interrupt is entered, let time record the number of times the interrupt is entered.
To achieve a 1s timing, we only need to judge whether time is equal to 1000.
1000*1ms=1s
Then clear the time to 0 and count again.
#include "stm32f10x.h" #include "bsp_led.h" #include "bsp_TiMbase.h" volatile uint32_t time = 0; // ms timing variable /** * @brief Main function * @param nothing * @retval nothing */ int main(void) { /* led port configuration */ LED_GPIO_Config(); BASIC_TIM_Init(); while(1)//When 1s is up, LED1 turns over once and clears time to 0 { if ( time == 1000 ) /* 1000 * 1 ms = 1s Time out */ { time = 0; /* LED1 Reverse */ LED1_TOGGLE; } } }
At the end of the interrupt service program, the corresponding interrupt flag bit shall be cleared.
void BASIC_TIM_IRQHandler (void) { if ( TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET ) { time++; TIM_ClearITPendingBit(BASIC_TIM , TIM_FLAG_Update); } }
Configure timer interrupt priority and basic timer.
// Basic timer TIMx,x[6,7] timing initialization function #include "bsp_TiMbase.h" // Interrupt priority configuration static void BASIC_TIM_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; // Set interrupt group to 0 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // Set interrupt source NVIC_InitStructure.NVIC_IRQChannel = BASIC_TIM_IRQ ; // Set primary priority to 0 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // Set preemption priority to 3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } /* * Note: Tim_ There are five members in the timebaseinittypedef structure, and only one in the registers of TIM6 and TIM7 * TIM_Prescaler And TIM_Period, so when using TIM6 and TIM7, you only need to initialize these two members, * The other three members are general timer and advanced timer *----------------------------------------------------------------------------- *typedef struct *{ TIM_Prescaler All have * TIM_CounterMode TIMx,x[6,7]No, everything else * TIM_Period All have * TIM_ClockDivision TIMx,x[6,7]No, everything else * TIM_RepetitionCounter TIMx,x[1,8,15,16,17]Only then *}TIM_TimeBaseInitTypeDef; *----------------------------------------------------------------------------- */ static void BASIC_TIM_Mode_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // Turn on the timer clock, i.e. the internal clock CK_INT=72M BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, ENABLE); // Automatically reload the value of the register, accumulating Tim_ An update or interrupt is generated after period + 1 frequency TIM_TimeBaseStructure.TIM_Period = BASIC_TIM_Period; // Clock pre division frequency is TIM_TimeBaseStructure.TIM_Prescaler= BASIC_TIM_Prescaler; // Clock frequency division factor, no basic timer, don't worry //TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; // Counter counting mode, the basic timer can only count up, and there is no setting of counting mode //TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; // Repeat the value of the counter. There is no basic timer. Don't worry //TIM_TimeBaseStructure.TIM_RepetitionCounter=0; // Initialization timer TIM_TimeBaseInit(BASIC_TIM, &TIM_TimeBaseStructure); // Clear Counter interrupt flag bit TIM_ClearFlag(BASIC_TIM, TIM_FLAG_Update); // Open Counter interrupt TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE); // Enable counter TIM_Cmd(BASIC_TIM, ENABLE); } void BASIC_TIM_Init(void) { BASIC_TIM_NVIC_Config(); BASIC_TIM_Mode_Config(); }