Basic timer of STM32

Posted by jimmyhumbled on Sun, 23 Jan 2022 14:58:08 +0100

basic timer

Basic framework

Clock source

Because the basic timer can only select: internal clock.

In STM32F103, the basic timers TIM6 and TIM7 are mounted on APB1, so the clock is originally the clock frequency value of APB1: 36MHZ, but please see the clock tree in the data manual of STM32F103.

What can we see from this??? Even if we circle the part, if the clock prescaler coefficient is 1, then the frequency is based on the bus frequency × 2, i.e. 36 × 2==72Mhz.

Why know the size of this value?

When configuring the library function, we need to know which bus it is mounted on, so that we can turn on its clock. When configuring the counting frequency division factor and technical cycle, we need to know this value, so that we can calculate the final time value.

//Turn on timer clock
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
TIM_TimeBaseInitStructure.TIM_Period = (8000-1);//8000
TIM_TimeBaseInitStructure.TIM_Prescaler = (9000-1);//9000

Why subtract 1 here? Because: counting starts from 0, and there are actually 8000 values from 0 to 7999, so setting (8000-1) here is the same as frequency division. As for why this value is set here, it is based on actual needs. This is discussed below.

Counting part

According to the script timer function block diagram, you can see:

The first is CK_PSC, this value is actually the clock from the internal clock, that is, CK as we mentioned above_ PSC = clock of apb1 × 2==36 × 2=72Mhz.

Secondly, after a PSC prescaler, even if it is set in the firmware library, for example, below, we set it to (9000-1), and the maximum value is 0xFFFF.

TIM_TimeBaseInitStructure.TIM_Prescaler = (9000-1);//9000

Can we get CK according to this frequency division value_ CNT (counter clock frequency), yes, CK here_ CNT=CK_ PSC/PSC=72Mhz/9000=8Khz.

The meaning here is to count every 1 / 8kHz, because our basic timer can only count up, that is, the time required to count from 0 to 1 is 1 / 8kHz. Similarly, the time required for 1 to 2, 2 to 3... Is also 1 / 8kHz.

We know that the time of each count is 1/8khz. How many times?

TIM_TimeBaseInitStructure.TIM_Period = (8000-1);//8000	

We can set the count 8000 times here. This value can be set according to the actual needs. The maximum value is the same as the above frequency division coefficient. For a 16 bit counter, the maximum value is 0xFFFF, that is 65535!

Each count is 1/8khz and 8000 times. Is the total time: 1/8khz × 8000==1s.

Yes, yes, it's 1s counting once, and then we let him generate an interrupt. Automatic reload register, advanced timer only, basic timer does not, so we stay in the advanced timer to explain.

To sum up, we set an interrupt every 1s.

The code is as follows:

BasicTime.c Documents

#include "./bsp_basictime/bsp_basictime.h"

//Configure interrupt priority
static void BasicTime_NVIC_Init(void)
{	
	NVIC_InitTypeDef	NVIC_InitStructure = {0};
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//Configure the interrupt priority group. Since there is only one interrupt, you can configure it here
	NVIC_InitStructure.NVIC_IRQChannel = Basic_TIMx_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

void BasicTime_Init(void)
{
	TIM_TimeBaseInitTypeDef	TIM_TimeBaseInitStructure = {0};
	//Turn on timer clock
	Basic_TIMx_APBClockCmd(Basic_TIMx_APB_Periph,ENABLE);
	//Configure the timer accordingly
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//The basic timer can only count up
	TIM_TimeBaseInitStructure.TIM_Period = Basic_TIMx_Period;//8000
	TIM_TimeBaseInitStructure.TIM_Prescaler = Basic_TIMx_Prescaler;//9000
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//Only advanced timers have this function.
	TIM_TimeBaseInit(Basic_TIMx,&TIM_TimeBaseInitStructure);
	//First clear the update interrupt flag bit of TIM to avoid affecting our update interrupt
	TIM_ClearFlag(Basic_TIMx,TIM_FLAG_Update);
	//Call interrupt priority function
	BasicTime_NVIC_Init();
	//Start timer update interrupt
	TIM_ITConfig(Basic_TIMx,TIM_IT_Update,ENABLE);
	//Start timer
	TIM_Cmd(Basic_TIMx,ENABLE);
}

BasicTime.h file

#ifndef __BSP_BASICTIME_H
#define	__BSP_BASICTIME_H

#include "stm32f10x.h"
//If you use the basic timer TIM7, you only need to use the following basic timer_ Change tim6 to Basic_TIM7 is enough
#define   Basic_TIM6

#ifdef 	 Basic_TIM6 / / use basic timer 6
#define    Basic_TIMx					TIM6
#define    Basic_TIMx_APBClockCmd		RCC_APB1PeriphClockCmd
#define    Basic_TIMx_APB_Periph		RCC_APB1Periph_TIM6
#define    Basic_TIMx_IRQn				TIM6_IRQn
#define    Basic_TIMx_IRQHandler		TIM6_IRQHandler
#define    Basic_TIMx_Period			(8000-1)
#define    Basic_TIMx_Prescaler			(9000-1)
#else 		// Use basic timer 7
#define    Basic_TIMx					TIM7
#define    Basic_TIMx_APBClockCmd		RCC_APB1PeriphClockCmd
#define    Basic_TIMx_APB_Periph		RCC_APB1Periph_TIM7
#define    Basic_TIMx_IRQn				TIM7_IRQn
#define    Basic_TIMx_IRQHandler		TIM7_IRQHandler
#define    Basic_TIMx_Period			(8000-1)
#define    Basic_TIMx_Prescaler			(9000-1)
#endif

extern void BasicTime_Init(void);
#endif /* __LED_H */

Interrupt function file content

void Basic_TIMx_IRQHandler(void)
{
	if(TIM_GetITStatus(Basic_TIMx,TIM_IT_Update) == SET)//If an update interrupt occurs, enter this function once
	{
		//1 s, reverse LED1 lamp once
		LED3_TOGGLE;
		TIM_ClearITPendingBit(Basic_TIMx,TIM_IT_Update);//Clear the interrupt flag bit to re-enter the interrupt next time
	}
}

summary

The main function of the basic timer is timing. We can use it to accurately locate the time, and then do some operations, such as lighting a light, sending content through the serial port, variable increment and so on.

Readme: come on, boy, don't forget your original heart!

Learn something, in order to strengthen the country!

Topics: stm32