STM32定时器(TIM)中断

发布时间 2023-07-27 20:43:20作者: LInguistic-零点

一、什么是定时器中断?

大白话理解:使用一个定时器进行计时(计数),数数的方式可以从上到下(从设定值到0),也可从下到上(从0 到设定值),或者中间计数(一般用不上,记住前面两者解决大部分问题,) 要学会释怀自己,哈哈(允许我找个不会的借口)。

当计数完成以后,将会发出冲断请求(就是给中断控制系统说,我想要中断一下,去干点别的事情)。如果中断控制系统同意中断,那么将会发生中断,如果不同意,那么中断失败。

二、定时器的类型特点(简答了解一下即可)

定时器分为高级定时器 、 通用定时器和基本定时器 (效果见名知意),需要注意的是,不同的控制芯片定时器的数量可能不同。使用前首先查找相应文件,看看是否觉有自己需要的定时器。

使用定时器的时候需要注意定时器所挂在的时钟。(STM32F103C8T6)没有四个定时器(TIM1~TIM4)

本次测试使用的是TIM2定时器,实现的效果是每次定时1s进行一次LED闪烁。

16位计数器: 用于计数,每来一个时钟,系统自动在所管理的数字加1.,计数到目标之后,将会自动清零,进行下一次计数。

预分频器: 对计数器的时钟进行分频,如果不分频默认是72Mhz

自动重装寄存器: 计数的目标值,当计数器的值达到该目标值后将会发生中断。(简单的理解就是计多少个数以后开始发生中断)

注意: 上面的寄存器都是16位的。所以单片机的最大定时时间为:

59.65s=1/72MHZ/65536/65536  

小知识: 一个定时器的输出作为另一个定时器的输入,实现定时器套娃,单片机的最大定时为24万亿年 (一本正经的胡说)

 

前面的都不重要,下面好好看一下彩色这张图,其实我们主要的就是要学会寄存器的使用和配置。本次测试使用的是内部时钟,正如你所看见的,定时器的是具有多种的,本次先使用内部使用。

需要特别的注意的就是三个模块的配置:时钟源配置、时基单元配置、中断控制配置三部分。

好了,废话不多说,直接看程序吧。

Code : timer.c

#include "timer.h"
#include "led.h"
extern uint16_t Num;
void TimerInit(void)
{
//打开定时器时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //定时器2是通用定时器,其时钟挂在到APB1时钟线上
//配置定时器2的时钟源来自内部时钟源,其实这里系统默认的就是内部时钟,所以这一步配置可以省去
TIM_InternalClockConfig(TIM2);

//定时器结构体配置
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1 ; //内部时钟分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period=7200-1; //定时器溢出值
TIM_TimeBaseInitStructure.TIM_Prescaler=10000-1; //分频系数
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0; //这里使用的是通用定时器没有复用计数功能,这里设置为0

//配置定时器2初始化
TIM_TimeBaseInit(TIM2 ,&TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);//定时器为确保初始时候具有有效的数据,因为数据是在缓冲区中,为确保预分频中的值具有意义数据,
//系统自动产生了一个更新事件,需要使用将会导致一初始化定时器就触发更新中断事件,导致一启动就进入中断程序,所以需要进行一次中断标志位清零
/* Generate an update event to reload the Prescaler and the Repetition counter
values immediately */
//定时器中断
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//中断定时器为2 ,中断模式为数据更新时中断

//配置中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel= TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2,ENABLE); //使能定时器
}

//中断相应函数
void TIM2_IRQHandler(void )
{
if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update)==SET)
{
Num++;
TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);
}

}

Code : timer.h

#ifndef _TIMER_H_
#define _TIMER_H_
#include "stm32f10x.h" // Device header
void TimerInit(void);
#endif

 Code : main.c

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "timer.h"
uint16_t Num=0;
/*
功能的实现,注意在KEIL5中不要使用中文的空格这样将会出现错误。重点,重点,重点

*/
int main(){
Led_funcing();
TimerInit();
// int k=5;
while(1)
{
if(Num%2==0)
{
GPIO_ResetBits(GPIOC,GPIO_Pin_13);

}else
{
GPIO_SetBits(GPIOC,GPIO_Pin_13);
}
if(Num==20)
{
Num=0;
}
}
}

效果很好,小伙伴们快操练起来。