STM32学习记录 -- 通用定时器的配置(TIM2-TIM5)

前言

        在我们编代码的时候,往往需要固定一程序心跳包去进行一个保活,或者给一个程序运行一个固定的时候,再或者是PWM的使用,都离不开定时器的使用,不仅方便我们处理数据,还给我们节约了MCU的内存,让我们的程序可以更加高效的执行起来


🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎

一.定时器的配置

1.timer.c

把TIM配置进行了封装处理,更加方便我们的配置和修改

#include "timer.h"	
#include "led.h"
/*********************************************************************************
* @Function	: 通用定时器的选择(TIM2-TIM5)
*	@Author   : HR
* @Date			: 2022-08-30
**********************************************************************************/
#if GENERAL_TIM2
		U16 Usart3_Time = 0; // ms 计时变量
		U16 Usart4_Time = 0; // ms 计时变量 
		U16 Usart5_Time = 0; // ms 计时变量 
#endif
#if GENERAL_TIM3
		U32 time = 0; // ms 计时变量 
#endif
#if GENERAL_TIM4
		U16 time_4 = 0; // ms 计时变量 
#endif
#if GENERAL_TIM5
		U16 time_5 = 0; // ms 计时变量 
#endif
/*********************************************************************************
* @Function	: TIM定时器选择
* @Input		: time,TIM定时器(TIM_2-TIM_5)
* @Output		:	TIM模块
* @Return		: None
* @Others		:	None
* @Date			: 2022-08-30
**********************************************************************************/
static TIM_TypeDef * TimeModule_get( TimeModule time )
{
	TIM_TypeDef * timeTemp;
	switch( ( U8 )time )//UART模块选择
	{
#if GENERAL_TIM2
		case TIM_2:
			timeTemp = TIM2;
		break;
#endif
#if GENERAL_TIM3
		case TIM_3:
			timeTemp = TIM3;
		break;
#endif
#if GENERAL_TIM4
		case TIM_4:
			timeTemp = TIM4;
		break;
#endif
#if GENERAL_TIM5
			case TIM_5:
				timeTemp = TIM5;
			break;
#endif
	}
  return timeTemp;
}
/*********************************************************************************
* @Function	: TIM定时器中断初始化
* @Input		: time,TIM定时器(TIM_2-TIM_5)
*						PreemptionPriority,抢占优先级
*						SubPriority,子优先级
* @Output		:	None
* @Return		: None
* @Others		:	None
* @Date			: 2022-08-30
**********************************************************************************/
static void GENERAL_TIM_NVIC_Config( TimeModule time, U8 PreemptionPriority, U8 SubPriority)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	
  // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);	// 设置中断组为0
	//Usart NVIC 配置
	switch( ( U8 )time )//中断通道配置
	{
		case TIM_2: NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;break; //TIM2中断
		case TIM_3: NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;break;
		case TIM_4: NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;break;
		case TIM_5: NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;break;
	}
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= PreemptionPriority ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = SubPriority;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
}
/*********************************************************************************
* @Function	: TIM时钟使能
* @Input		: time,time时钟(TIM_1-TIM_5)
* @Output		:	None
* @Return		: None
* @Others		:	None
* @Date			: 2022-08-30
**********************************************************************************/
static void GENERAL_TIMClock_Enable( TimeModule time)
{
	switch( (U8)time )
	{
		case TIM_2: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); break;//通用定时器2时钟使能
		case TIM_3: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); break;//通用定时器2时钟使能
		case TIM_4: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); break;//通用定时器2时钟使能
		case TIM_5: RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); break;//通用定时器2时钟使能
	}
}

/*
 * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
 * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
 * 另外三个成员是通用定时器和高级定时器才有.
 *-----------------------------------------------------------------------------
 *typedef struct
 *{ TIM_Prescaler            都有
 *	TIM_CounterMode			     TIMx,x[6,7]没有,其他都有
 *  TIM_Period               都有
 *  TIM_ClockDivision        TIMx,x[6,7]没有,其他都有
 *  TIM_RepetitionCounter    TIMx,x[1,8,15,16,17]才有
 *}TIM_TimeBaseInitTypeDef; 
 *-----------------------------------------------------------------------------
 */
static void GENERAL_TIM_Mode_Config(TimeModule time)
{
		TIM_TypeDef * timeTemp;
		TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;	
		timeTemp = TimeModule_get( time );//TIME时钟选择
	
		// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
    TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_Period;
	  // 时钟预分频数
    TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_Prescaler;	
		// 时钟分频因子 ,没用到不用管
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;		
		// 计数器计数模式,设置为向上计数
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; 		
		// 重复计数器的值,没用到不用管
		TIM_TimeBaseStructure.TIM_RepetitionCounter=0;	
	  // 初始化定时器
    TIM_TimeBaseInit(timeTemp, &TIM_TimeBaseStructure);
		// 清除计数器中断标志位
    TIM_ClearFlag(timeTemp, TIM_FLAG_Update);
		// 开启计数器中断
    TIM_ITConfig(timeTemp,TIM_IT_Update,ENABLE);
		// 使能计数器
    TIM_Cmd(timeTemp, DISABLE); //关闭定时器
}
/*********************************************************************************
* @Function	: TIM2-5 初始化
* @Input		: time,TIM定时器(TIM_2-TIM_5)
*						PreemptionPriority,抢占优先级
*						SubPriority,子优先级
* @Output		:	None
* @Return		: None
* @Others		:	None
* @Date			: 2022-08-30
**********************************************************************************/
void GENERAL_TIM_Init(TimeModule time,U8 PreemptionPriority, U8 SubPriority)
{
	GENERAL_TIMClock_Enable(time); //TIM使能化
	GENERAL_TIM_NVIC_Config(time,PreemptionPriority,SubPriority); //TIM中断优先级配置
	GENERAL_TIM_Mode_Config(time); //TIM初始化	
}
/*********************************************************************************
* @Function	:  TIMER2定时器中断服务
* @Input		:  None
* @Output		:	 None
* @Return		:  None
* @Others		:	 None
* @Date			:  2022-08-30
**********************************************************************************/
#if GENERAL_TIM2 
void TIM2_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
	{
		if(Usart5_Time>0){
			Usart5_Time++;//串口五接收间隔判断
		}else if(Usart4_Time>0){
			Usart4_Time++;//串口四接收间隔判断
		}else if(Usart3_Time>0){
			Usart3_Time++;//串口三接收间隔判断
		}
		//满足条件关定时器
		if(Usart5_Time==10||Usart3_Time==10||Usart4_Time==10){
			TIM_Cmd(TIM2, DISABLE); //关闭定时器
		}
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update  );  //清除TIMx更新中断标志
	}
}
#endif
/*********************************************************************************
* @Function	:  TIMER3定时器中断服务
* @Input		:  None
* @Output		:	 None
* @Return		:  None
* @Others		:	 None
* @Date			:  2022-08-30
**********************************************************************************/
#if GENERAL_TIM3 
void TIM3_IRQHandler(void)   //TIM3中断
{
	U8 i;
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
	{
		if(time>0){
			time++;//串口五接收间隔判断
		}
		//满足条件关定时器
		if(time==10000){
			LED2_OFF;
			time=0;
			TIM_Cmd(TIM3, DISABLE); //关闭定时器
		}
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志 
	}
}
#endif



2.timer.h

在主函数只需要选择我们需要配置的通用定时器即可

例如 

GENERAL_TIM_Init(TIM_2,0,3);        //初始化定时器2,抢占优先级,子优先级(防止掉帧)

#ifndef __TIMER_H
#define __TIMER_H

#include "tool.h"
#include "stm32f10x_tim.h"
/**************通用定时器TIM参数定义,只限TIM2、3、4、5************/
// 当需要哪个定时器的时候,只需要把下面的宏定义改成1即可
#define GENERAL_TIM2    1
#define GENERAL_TIM3    1
#define GENERAL_TIM4    0
#define GENERAL_TIM5    0
/*********************************************************************************
* @Function	: TIME实例
**********************************************************************************/
typedef enum 
{
	TIM_2,
	TIM_3,
	TIM_4,
	TIM_5,
	TIME_NUM
}TimeModule;
/*********************************************************************************
* @Function	: 固定分频率
**********************************************************************************/
#define            GENERAL_TIM_Period            (1000-1)
#define            GENERAL_TIM_Prescaler         71 //时钟预分频数

/*********************************************************************************
* @Function	: TIM2-5 初始化
* @Input		: time,TIM定时器(TIM_2-TIM_5)
*						PreemptionPriority,抢占优先级
*						SubPriority,子优先级
* @Output		:	None
* @Return		: None
* @Others		:	None
* @Date			: 2022-08-30
**********************************************************************************/
void GENERAL_TIM_Init(TimeModule time,U8 PreemptionPriority, U8 SubPriority);

#endif

🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎

二.定时器的使用

1.PWM输出使用

使用TIM的分频率去控制PWM的输出,做到控制端口电压的输出,可实现呼吸灯,电机转速等控制效果

2.软件定时器的使用

例如我们执行一个开关的的程序,当我们固定一个动作打开灯后,在这个打开灯的时候就开启我们的定时器,在定时器里面做一个固定时间再关闭我们的灯

例如下列代码

在主函数首先进行TIM3的配置

GENERAL_TIM_Init(TIM_3,0,2);		//初始化定时器3,抢占优先级,子优先级(LED定时器)

 对TIM3的中断进行一个配置即可

/*********************************************************************************
* @Function	:  TIMER3定时器中断服务
* @Input		:  None
* @Output		:	 None
* @Return		:  None
* @Others		:	 None
* @Date			:  2022-08-30
**********************************************************************************/
#if GENERAL_TIM3 
void TIM3_IRQHandler(void)   //TIM3中断
{
	U8 i;
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
	{
		if(time>0){
			time++;//串口五接收间隔判断
		}
		//满足条件关定时器
		if(time==10000){
			LED2_OFF;
			time=0;
			TIM_Cmd(TIM3, DISABLE); //关闭定时器
		}
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志 
	}
}
#endif

3.串口防止掉帧使用等

道理相同,我们主要是防止串口出现丢包情况。所以配置一个定时器检测他的接收情况 ,如果串口在我们规定的时间内没有再有数据的输出,则说明我们的串口数据接收完成

/*********************************************************************************
* @Function	:  TIMER2定时器中断服务
* @Input		:  None
* @Output		:	 None
* @Return		:  None
* @Others		:	 None
* @Date			:  2022-08-30
**********************************************************************************/
#if GENERAL_TIM2 
void TIM2_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
	{
		if(Usart5_Time>0){
			Usart5_Time++;//串口五接收间隔判断
		}else if(Usart4_Time>0){
			Usart4_Time++;//串口四接收间隔判断
		}else if(Usart3_Time>0){
			Usart3_Time++;//串口三接收间隔判断
		}
		//满足条件关定时器
		if(Usart5_Time==10||Usart3_Time==10||Usart4_Time==10){
			TIM_Cmd(TIM2, DISABLE); //关闭定时器
		}
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update  );  //清除TIMx更新中断标志
	}
}
#endif

🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎🚎

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿柒学起来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值