当前位置: 首页 > news >正文

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

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

相关文章:

  • node搭建服务器
  • 域名解析信息易语言代码
  • 【GNN报告】蒙特利尔大学朱兆成:基于图神经网络的知识图谱推理
  • ATF启动(二):BL1
  • Nginx之正则表达式、location匹配简介以及rewrite重写
  • Kafka 集群安装及常用命令
  • C++变量和基本类型
  • 室温熔盐-Romm Temperature Melten Salt-RTMS-离子液体
  • 无胁科技-TVD每日漏洞情报-2022-9-1
  • C++征途 --- 内建函数对象
  • 李沐d2l(十一)--图像增广
  • ubuntu 环境安装微信
  • pdf怎么压缩到又小又清晰?
  • 三目运算符的多层嵌套
  • 【一生一芯】Chap.1 “一生一芯”实验环境配置| VMware安装Ubuntu20.04 | PA工程配置 | 解决llvm版本问题
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • C++入门教程(10):for 语句
  • canvas 绘制双线技巧
  • Git初体验
  • HomeBrew常规使用教程
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • Netty 4.1 源代码学习:线程模型
  • React-Native - 收藏集 - 掘金
  • Redis 懒删除(lazy free)简史
  • Web Storage相关
  • 前端工程化(Gulp、Webpack)-webpack
  • 使用权重正则化较少模型过拟合
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​决定德拉瓦州地区版图的关键历史事件
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • $.ajax()方法详解
  • (13)Hive调优——动态分区导致的小文件问题
  • (ZT)北大教授朱青生给学生的一封信:大学,更是一个科学的保证
  • (七)Knockout 创建自定义绑定
  • (十一)c52学习之旅-动态数码管
  • (转)visual stdio 书签功能介绍
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • (转)清华学霸演讲稿:永远不要说你已经尽力了
  • (转)微软牛津计划介绍——屌爆了的自然数据处理解决方案(人脸/语音识别,计算机视觉与语言理解)...
  • .cfg\.dat\.mak(持续补充)
  • .NET 中的轻量级线程安全
  • .net 桌面开发 运行一阵子就自动关闭_聊城旋转门家用价格大约是多少,全自动旋转门,期待合作...
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .NET处理HTTP请求
  • .NET建议使用的大小写命名原则
  • .Net下使用 Geb.Video.FFMPEG 操作视频文件
  • [Angular 基础] - 自定义指令,深入学习 directive
  • [AR]Vumark(下一代条形码)
  • [BZOJ4337][BJOI2015]树的同构(树的最小表示法)
  • [C#][opencvsharp]opencvsharp sift和surf特征点匹配
  • [C++打怪升级]--学习总目录
  • [C++进阶篇]STL中vector的使用
  • [COGS 622] [NOIP2011] 玛雅游戏 模拟
  • [c语言]小课堂 day2