一、定时器的简单介绍(例程在结语部分,可以直接跳转)

定时器,一般分为三种,基础定时器,通用定时器和高级定时器。

一般来说,STM32F103的基础定时器为TIM6、TIM7。通用定时器为TIM2~5,高级定时器则为TIM1和TIM8.

在STM32F03C8T6中,有一个高级定时器,为TIM1,三个通用定时器,TIM2、TIM3和TIM4。

这个为基础定时器的框图

这个为高级定时器的框图

由此可见,定时器之间的差距。本笔记,主要介绍的还是通用定时器。对于高级会提上两嘴。

废话不多说,先上手册。

通过手册,我们可以了解通用定时器的主要功能。

二、通用定时器的结构

1、通用定时器的基本结构

分析图框,我们大概可以了解定时器的基本结构

2、通用定时器的计数方式

通用定时器有三种计数模式。

第一种是向上计数模式

第二种是向下计数

还有中央对齐

三、实现定时器中断的代码

1、配置定时器

首先开启和选择时钟

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	TIM_InternalClockConfig(TIM2);//选择内部时钟

之后配置时机单元,用结构体来进行配置

	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择分频倍率,此为不分频
	//选择内部时钟的话,不分频的情况下,是72MHZ
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//选择计数方式,此为向上计数
    //
	TIM_TimeBaseInitStructure.TIM_Period = 10000-1;//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200-1;//PSC
    //这两条确定定时器的定时时间,此为1ms
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//高级定时器才会用到,我们填0
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);

注意,对于定时器的定时频率,也就是定时时间,我们可以用这个公式来确定

2、配置中断

接下来对于中断进行配置。

首先使能中断,并将TIM2选择为更新中断

	TIM_ClearFlag(TIM2,TIM_FLAG_Update);//清除中断标志位
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断,TIM_IT_Update为更新中断

接下来,为中断优先级进行分组。

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC优先级分组

然后配置中断的结构体,确定中断通道和优先级

	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);//使能定时器

3、中断函数

当定时器溢出,就会触发中断,随后就会进入中断函数,并执行中断函数中的代码。当中断函数中的代码执完毕后,程序会回到中断点,继续按照原来的代码进行执行。

打开启动文件,可以在里面找到TIM2的中断函数

void TIM2_IRQHandler(void)

当触发中断,就会进入这个函数。

但是如此还不算万事大吉,我们还要先检查一下中断标志位

	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)//获取中断标志位并进行判断
	{
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志位
	}

如此,才算真正写完中断,要想让中断执行的代码,写在判断内部即可

四、结语

最后总结一下,定时器是STM32中,功能、结构最复杂的片上外设。

此笔记只是介绍了通用定时器,对于高级定时器,与通用定时器,还要许多不一样的地方。

还需努力进行探索。

要想真正弄明白,还是要对手册进行深度研究。

最后,贴上完整例程

#include "stm32f10x.h"                  // Device header

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	TIM_InternalClockConfig(TIM2);//选择内部时钟
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择分频倍率,此为不分频
	//选择内部时钟的话,不分频的情况下,是72MHZ
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//选择计数方式,此为向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 10000-1;//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200-1;//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//高级定时器才会用到,我们填0
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);//清除中断标志位
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断,TIM_IT_Update为更新中断
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC优先级分组
	
	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_GetITStatus(TIM2,TIM_IT_Update)==SET)
	{
		
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐