STM32 TIM定时器配置

TIM简介

TIM(Timer)定时器

定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断

16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时

不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能

根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型

定时器类型

定时中断基本结构

计数器时序:


计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)

= CK_PSC (72M)/ (PSC + 1) / (ARR + 1)

预分频器时序:


计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)

定时器中断代码:

TIM函数介绍:

下面的函数对应着定时中断的结构

复制代码
//时基单元初始化
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

//将结构体变量赋一个默认值
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

//使能计数器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

//使能中断输出信号
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);

//选择内部时钟
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);

//选择ITRx其他定时器时钟
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);

//选择TIx捕获通道的时钟
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
                                uint16_t TIM_ICPolarity, uint16_t ICFilter);

//选择ETR通过外部时钟模式1输入的时钟
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                             uint16_t ExtTRGFilter);

//选择ETR通过外部时钟模式2输入的时钟
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, 
                             uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);

//单独配置ETR引脚的预分频器、极性、滤波器这些参数
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                   uint16_t ExtTRGFilter);

参数更改函数:

复制代码
//单独写预分频值
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);

//用来更改计数器的计数模式
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);

//自动重装器预装功能配置
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

//给计数器写入一个值
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);

//给自动重装器写入一个值
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);

//获取当前计数器的值
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);

//获取当前的预分频器的值
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);

配置定时器(内部时钟):

打开时钟

这次初始化TIM2,也就是通用定时器,TIM2是APB1的总线外设。

复制代码
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//打开TIM2的外设时钟

选择内部时钟

这里不写这行代码也行,因为定时器上电后默认就是使用内部时钟

复制代码
 TIM_InternalClockConfig(TIM2);//选择内部时钟

配置时基单元

复制代码
//-----------------------------配置时基单元---------------------------------
	
	 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义TIM结构体变量
	
	 TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;   //时钟分频
	 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初始化
	
	//-----------------------------配置时基单元---------------------------------

使能更新中断

复制代码
 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);						//开启更新中断到NVIC通路

NVIC配置

这里的中断通道选择TIM2的中断通道。

复制代码
//-----------------------------NVIC配置-------------------------------------
	
	NVIC_InitTypeDef NVIC_InitStructure;//定义NVIC结构体变量
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择中断分组2
	
	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);//NVIC初始化
	
//-----------------------------NVIC配置-------------------------------------

启动定时器:

复制代码
TIM_Cmd(TIM2,ENABLE);//启动定时器

整体函数:

cs 复制代码
void Timer_Init(void)
{
	 //---------------------------定义结构体变量-------------------------------
	
	 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义TIM结构体变量
	 NVIC_InitTypeDef NVIC_InitStructure;//定义NVIC结构体变量
	
	//---------------------------定义结构体变量-------------------------------
	
	 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//打开TIM2的外设时钟
	
	 TIM_InternalClockConfig(TIM2);//选择内部时钟
	
	//-----------------------------配置时基单元---------------------------------
	
	 TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;		 //时钟分频
	 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初始化
	
	//-----------------------------配置时基单元---------------------------------
	 
	 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);						//开启更新中断到NVIC通路
	
	 
	//-----------------------------NVIC配置-------------------------------------
	
	
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择中断分组2
	
	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);//NVIC初始化
	
	//-----------------------------NVIC配置-------------------------------------
	
	 TIM_Cmd(TIM2,ENABLE);//启动定时器
}

中断函数:

实现定时器计时功能。

复制代码
uint16_t Num = 0;
//中断函数

void TIM2_IRQHandler(void)
{
	//获取中断标志位,判断是否触发中断
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		
		Num++;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志位
		
		
	}
	
}

这里定义了一个变量Num,所以需要在头文件了extern一下,让其他工程文件也能用这个变量。

主函数:

完成了定时器计时功能,没过一秒,Num + 1.在屏幕上显示出来。

cs 复制代码
#include "timer.h"
int main(void)
{
	LED_Init();
	OLED_Init();
	Timer_Init();
	OLED_ShowString(1, 3, "Num:");
	while(1)
    {
	
	    OLED_ShowNum(1, 5, Num, 5);
	

    }	
	
	
}

这里上电以及复位不是从零开始,需要在NVIC配置之前清除一下标志位

配置外部时钟:

选择外部时钟模式

与内部时钟配置一样,只需要选择外部时钟模式以及加一个GPIO配置。

配置GPIO

cs 复制代码
//-----------------------------GPIO配置-------------------------------------
	
	 GPIO_InitTypeDef GPIO_InitStructure;				//定义GPIO结构体变量
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;		//选择上拉输入
	 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;    		//配置引脚
	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速率
	
	 GPIO_Init(GPIOA, &GPIO_InitStructure);//GPIO初始化
	
//-----------------------------GPIO配置-------------------------------------

整体函数配置:

cs 复制代码
void Timer_Init(void)
{
	 //---------------------------定义结构体变量-------------------------------
	
	 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义TIM结构体变量
	 NVIC_InitTypeDef NVIC_InitStructure;							 //定义NVIC结构体变量
	 GPIO_InitTypeDef GPIO_InitStructure;							 //定义GPIO结构体变量
	//---------------------------定义结构体变量-------------------------------
	
	 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//打开TIM2的外设时钟
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//打开GPIO A族时钟
	 TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted,0x0F);//选择外部时钟模式
	
	//-----------------------------GPIO配置-------------------------------------
	
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;		//选择上拉输入
	 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;    		//配置引脚
	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速率
	
	 GPIO_Init(GPIOA, &GPIO_InitStructure);//GPIO初始化
	
	//-----------------------------GPIO配置-------------------------------------
	
	//-----------------------------配置时基单元---------------------------------
	
	 TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;		 //时钟分频
	 TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式  这里选择向上计数
	 TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;							 //周期 就是ARR自动重装器的值
	 TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;						 //是PSC预分频器的值
	 TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;						 //重复计数器的值(这个是高级寄存器才有的,这里不需要用直接给0)
	 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);						 //TIM初始化
	
	//-----------------------------配置时基单元---------------------------------
	 
	 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);						//开启更新中断到NVIC通路
	
	 TIM_ClearITPendingBit(TIM2,TIM_IT_Update);        		//清除标志位
	//-----------------------------NVIC配置-------------------------------------
	
	
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择中断分组2
	
	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);//NVIC初始化
	
	//-----------------------------NVIC配置-------------------------------------
	
	 TIM_Cmd(TIM2,ENABLE);//启动定时器
}

功能中断函数:

cs 复制代码
uint16_t Num = 0;
//中断函数

void TIM2_IRQHandler(void)
{
	//获取中断标志位,判断是否触发中断
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		
		Num++;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志位
		
		
	}
	
}

uint16_t Timer_Getcount(void)
{
	return TIM_GetCounter(TIM2);
}

主函数:

cs 复制代码
#include "timer.h"
int main(void)
{
	LED_Init();
	OLED_Init();
	Timer_Init();
	OLED_ShowString(1, 1, "Num:");
	OLED_ShowString(2, 1, "CNT:");
	while(1)
    {
	    OLED_ShowNum(1, 5, Num, 5);
	    OLED_ShowNum(2, 5, Timer_Getcount(), 5);
    }		
}
相关推荐
lingzhilab1 小时前
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
stm32·嵌入式硬件·信息可视化
小智学长 | 嵌入式5 小时前
SOC-ESP32S3部分:26-物联网MQTT连云
单片机·物联网·esp32
GXSC6 小时前
国芯思辰| AD7894的优质替代方案:SC1424模数转换器在分布式控制系统中的应用优势
嵌入式硬件
lixzest6 小时前
Keil调试模式下,排查程序崩溃简述
stm32·单片机
极术社区7 小时前
【Mini-F5265-OB开发板试用测评】显示RTC日历时钟
单片机·嵌入式硬件·实时音视频
WIZnet7 小时前
第二十八章 RTC——实时时钟
嵌入式硬件·时间戳·wiznet·高性能以太网单片机·w55mh32·rtc实时时钟·时钟分频
小智学长 | 嵌入式8 小时前
SOC-ESP32S3部分:31-ESP-LCD控制器库
单片机·物联网·esp32
广药门徒14 小时前
最小硬件系统概念及其组成
单片机·嵌入式硬件
GXSC17 小时前
国芯思辰|SCS5501/5502芯片组打破技术壁垒,重构车载视频传输链路,兼容MAX9295A/MAX96717
嵌入式硬件
啵啵学习17 小时前
Linux 里 su 和 sudo 命令这两个有什么不一样?
linux·运维·服务器·单片机·ubuntu·centos·嵌入式