Detailed explanation of general timer interrupt experiment

table of Contents

General timer interrupt experiment

Timer interrupt clock source analysis

Teach you how to look at the logic signal diagram

Up-counting mode (clock division factor = 1)

Center-aligned counting mode (clock division factor=1, ARR=6)

Introduction to related registers

Event generation register (TIMx_EGR)

Status register (TIMx_SR)

Counter (TIMx_CNT)

Prescaler (TIMx_PSC)

Auto reload register (TIMx_ARR)

Control register 1 (TIMx_CR1)

Use library functions to configure general-purpose timers with interrupts

Introduction to library functions

Selection of timer parameters

Design requirements

TIMX programming flow

Step 1: Initialize TIMER3

Step 2: Initialize Timer 3 (configure the value of ARR and PSC)

Step 3: Initialize the NVIC embedded interrupt vector

Step 4: Configure the interrupt of TIMX

Step 5: Enable TIMX peripheral

Step 6: Write the corresponding interrupt service function

Code example

Main.c

Led.c

Led.h.

Timer.h

Timer.c

operation result


General timer interrupt experiment

Timer interrupt clock source analysis

 

Our experiment uses the clock from the APB1 bus (AHB clock frequency is 72MHz). We noticed that in AHB->APB1 divider->APB1, if the division factor of the APB1 prescaler is 1, then the clock frequency of TIMXCLK is " TIMCLK=APB1=AHB", if the division factor of the APB1 prescaler is N (N is not 1), then the clock frequency of TIMXCLK is "TIMCLK=2xAPB1=2xAHB/N".

But when we call the initialization clock source library function provided by ST, the default division factor of the APB1 divider is 2, so the final TIMXCLK=2xAPB1=2xAHB/2=AHB.

 

TIMXCLK clock frequency = CLK_INT clock frequency, and then passed to CK_PSC through the trigger controller for the second frequency division processing, the final clock pulse received by the CNT counter is "CLK_INT/(CK_PSC+1)", (why the frequency division factor is CK_PSC +1 we will talk about it later)

Teach you how to look at the logic signal diagram

Up-counting mode (clock division factor = 1)

 

 

First, CK_INT is the initial clock source of TIMER, CNT_EN represents TIMER enable, CK_CNT is the pulse frequency received by the counter (after the frequency is divided in the CK_PSC register), the reload value of the counter register is 36, "interrupt event update" It is synchronized with "timer overflow" and "update interrupt flag set to 1," but we see that if we do not manually clear the interrupt flag, the system will always be in the execution interrupt regardless of whether the interrupt condition is met.

Center-aligned counting mode (clock division factor=1, ARR=6)

 

 

The center-aligned counting mode is somewhat different in that the interrupt is triggered when the up-count overflow and the down-count overflow respectively, and if we do not clear the interrupt flag after each interrupt, the interrupt behavior will always exist regardless of whether the interrupt condition is met.

Introduction to related registers

Event generation register (TIMx_EGR)

 

The update event interrupt is an ordinary interrupt executed by the general-purpose timer.

Status register (TIMx_SR)

 

Counter (TIMx_CNT)

 

Prescaler (TIMx_PSC)

 

Auto reload register (TIMx_ARR)

 

This register is used to reload the overflow value of the counter after the count value of the counter overflows.

Control register 1 (TIMx_CR1)

 

This register is used to request interrupts and configure the counter mode. Once the interrupt is triggered, all registers will be updated.

Use library functions to configure general-purpose timers with interrupts

Introduction to library functions

Library function name

Features

TIM_TimeBaseInit

Used to initialize the TIMX timer

TIM_Cmd

Enable or disable TIMx peripheral

TIM _ITConfig

After configuring the corresponding parameters of the NVIC, enable or disable the specified TIM interrupt

TIM_PrescalerConfig

Set TIMx prescaler

TIM_CounterModeConfig

Set TIMx counter mode

TIM_GetITStatus

Check whether the specified TIM interrupt occurs or not

TIM_ClearITPendingBit

Clear the interrupt pending bit of TIMx

TIM_GetFlagStatus

Check whether the specified TIM flag is set or not

TIM_ClearFlag

Clear the pending flag of TIMx

The difference between TIM_ClearITPendingBit and TIM_ClearFlag function

TIM_ClearITPendingBit clears some interrupt flag bits, and TIM_ClearFlag clears timer status flags, such as timer capture status bit timer trigger flag bit.

Selection of timer parameters

 

The general timer parameters mainly have two PSC prescaler coefficients and ARR counter reload value. The overflow time refers to "the time from 0x00 to TOP".

 

Design requirements

Through the timer interrupt configuration, interrupt once every 500ms, and then control the LED in the interrupt service function to realize the inversion (flashing) of the LED1 state.

TIMX programming flow

Step 1: Initialize TIMER3

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 使能APB1的外设时钟  

 

Step 2: Initialize Timer 3 (configure the value of ARR and PSC)

TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;  
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Down;  
TIM_TimeBaseInitStructure.TIM_Period = 0x1C20;  // 5000
TIM_TimeBaseInitStructure.TIM_Prescaler = 0x1388;  // 7200
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure); // 初始化TIMER3  

 

Step 3: Initialize the NVIC embedded interrupt vector

NVIC_InitTypeDef NVIC_InitStructure;  
  
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  
NVIC_Init(&NVIC_InitStructure); // 初始化NVIC嵌入式外部中断  

 

Why do we configure the NVIC interrupt vector grouping before the NVIC initialization?

The NVIC interrupt vector grouping is used to constrain all interrupt vectors. If we put it in a header file alone, we can’t express this meaning, and if we declare different interrupt vector groups in different header files, it will be messy. of.

Step 4: Configure the interrupt of TIMX

TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); // 配置TIMER3的具体中断行为  

 

Why the TIM interrupt channel of NVIC has been opened, and why do we also configure the TIMX interrupt?

What we enable at the beginning is the TIMX interrupt channel. The TIMX interrupt mode is very complicated and there are multiple interrupt modes. Therefore, we first enable the total interrupt channel of TIMX, and then further configure the attributes of the TIMX interrupt, such as different interrupt conditions: Up counting overflow, down counting overflow....

Step 5: Enable TIMX peripheral

TIM_Cmd(TIM3, ENABLE); // 使能TIMER3外设  

 

Step 6: Write the corresponding interrupt service function

void TIM3_IRQHandler() // 应该在相应的中断文件内编写中断服务函数  
{  
    if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET) // 由于定时器有多个中断模式,因此我们一定要检查相应的中断标志位  
    {  
        LED0 = !LED0;  
    }  
    TIM_ClearITPendingBit(TIM3, TIM_IT_Update); // 由于定时器有多个中断模式,因此我们一定要清除相应的中断标志位   
}  

 

Code example

Main.c

#include "led.h"  
#include "timer.h"  
#include "stm32f10x.h"  
#include "delay.h"  
  
int main()  
{  
    delay_init(); // 只有初始化系统systick时钟,我们才能调用delay系列函数  
    LED_InitConfig(); // LED初始化  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // NVIC中断向量分组应该先于NVIC初始化  
    TIMER_InitConfig(0x1C20, 0x1388); // 初始化TIMER3,其中PR=7200,ARR=5000  
      
    while(1)  
    {  
        LED1 = !LED1;  
        delay_ms(250);  
    }  
}  

 

Led.c

#include "led.h"  
#include "stm32f10x.h"  
  
void LED_InitConfig()  
{  
    GPIO_InitTypeDef GPIO_InitStructure;  
      
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); // 使能LED0,LED1的时钟  
      
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    GPIO_Init(GPIOB, &GPIO_InitStructure); // 配置LED0的GPIO输出属性  
      
    GPIO_ResetBits(GPIOB, GPIO_Pin_5); // 初始化PB5为低电平  
      
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    GPIO_Init(GPIOE, &GPIO_InitStructure); // 配置LED1的GPIO输出属性  
      
    GPIO_ResetBits(GPIOE, GPIO_Pin_5); // 初始化PE5为低电平  
}  

 

Led.h.

#ifndef _LED_H  
#define _LED_H  
  
#include "sys.h"  
  
void LED_InitConfig();  
  
#define LED0 PBout(5)  
#define LED1 PEout(5)  
  
#endif  

 

Timer.h

#ifndef _TIMER_H  
#define _TIMER_H  
  
#include "sys.h"  
  
void TIMER_InitConfig(u16 ARR, u16 PR);  
  
#endif  

 

Timer.c

 

operation result

 

 

Guess you like

Origin blog.csdn.net/weixin_45590473/article/details/108048325