stm32 basic timer

Posted by ilight on Sun, 27 Feb 2022 05:07:14 +0100

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();
}

Topics: Embedded system stm32