Realize timer interrupt function based on STM32F4 (Tim2, Tim3)


foreword

I haven't learned new content for many days, and today I will learn the universal timer.


1. Overview of the timer

The most basic function of the timer is timing. If the timer and GPIO are used together, a lot of functions can be realized, such as measuring the pulse width of the input signal, generating an output square wave, and so on. There are two advanced timers, nine general-purpose timers, and two basic timers in stm32f407. The main functions of the general-purpose timers are timing counting, PWM output, input capture, and output comparison.

The whole and source of the clock is shown in the figure below:
insert image description here
The timer mainly consists of several parts: the clock part on the top layer, the time counting part in the middle, the input capture part on the lower left and the output comparison part on the lower right. Among them, there are many sources of clocks, and the internal clock is the most used. The internal clock is generally the clock from the APB bus; ETR (External Trigger) is the clock from the outside, and ITRx is the output of the cascaded internal timer, which can be used to Make a cascading timer. The timer itself has a prescaler PSC, which is one of the important parameters that need to be set.

2. Routine implementation

1. Routine introduction

This time, there is no detailed introduction to the timer and the introduction of each parameter. For a novice, it is not the first time to understand everything. I think I have a general understanding first, and run the program first. Learn a little bit more when you use it.

We define two timer interrupts with different count values ​​to flash the LED to observe the difference between them.

2. Complete code

code show as below:

#include "stm32f4xx.h"                  // Device header
#include "sys.h"   						//定义的是位带操作文件,可不要

//gpio、nvic、timer需要用到的结构体
static GPIO_InitTypeDef  GPIO_InitStructure;
static NVIC_InitTypeDef NVIC_InitStructure;
static TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

//自定义的一个延时函数
void delay_ms(uint32_t n)
{
    
    
	while(n--)
	{
    
    
		SysTick->CTRL = 0; // Disable SysTick
		SysTick->LOAD = (168000)-1; // Count from 255 to 0 (256 cycles)
		SysTick->VAL = 0; // Clear current value as well as count flag
		SysTick->CTRL = 5; // Enable SysTick timer with processor clock
		while ((SysTick->CTRL & 0x00010000)==0);// Wait until count flag is set
	}
	
	SysTick->CTRL = 0; // Disable SysTick
}


//定时器3初始化函数
void Tim3_init(void)
{
    
    
	//使能定时器3硬件时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	//配置定时器3分频值、计数值
	TIM_TimeBaseStructure.TIM_Period = 10000/2-1;//计数值500ms
	TIM_TimeBaseStructure.TIM_Prescaler = 8400-1;//进行8400的预分频值 42*2Mhz/8400=10000hz 10000次计数就是1秒
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;//在f407不支持,没有时钟分频
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
	
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
	
	//配置定时器3中断的触发方式
	TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE);

	//配置定时器3的中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	//使能定时器3工作
	TIM_Cmd(TIM3, ENABLE);
	
}


void Tim2_init(void)
{
    
    
	//使能定时器2硬件时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	//配置定时器2分频值、计数值
	TIM_TimeBaseStructure.TIM_Period = 1000-1;//计数值100ms
	TIM_TimeBaseStructure.TIM_Prescaler = 8400-1;//进行8400的预分频值 42*2Mhz/8400=10000hz 10000次计数就是1秒
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;//在f407不支持,没有时钟分频
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
	
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
	
	//配置定时器2中断的触发方式
	TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);

	//配置定时器2的中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	//使能定时器2工作
	TIM_Cmd(TIM2, ENABLE);
	
}



int main(void)
{
    
    
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOE时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF时钟

	//GPIOF9,F10初始化设置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化
	
	
	
	GPIO_SetBits(GPIOF,GPIO_Pin_9 |GPIO_Pin_10);
	
	//定时器 3初始化
	Tim3_init();
	Tim2_init();
	while(1)
	{
    
    
		
	
		
	}
}

//查看向量表(misc.h)可以找到对应的中断函数名
void TIM3_IRQHandler(void)
{
    
    
	//判断标志位
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
	{
    
    
		PFout(10)^=1;//对led进行闪烁操作
		//清空标志位
		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
	}
}

void TIM2_IRQHandler(void)
{
    
    
	//判断标志位
	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
	{
    
    
		PFout(9)^=1;
		//清空标志位
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}


Summarize

The timer is a more important function, it takes time to learn, and it will be used in the following PWM output. If you can have time to learn some new knowledge every day, I believe that you will learn something when you accumulate it over time.

Guess you like

Origin blog.csdn.net/weixin_46155589/article/details/127435932
Recommended