stm32---定时器输入捕获

2023-09-13 10:58:36

一、输入捕获介绍

        在定时器中断实验章节中我们介绍了通用定时器具有多种功能,输入捕获就是其中一种。 STM32F1除了基本定时器TIM6和TIM7,其他定时器都具有输入捕获功能 。输入捕获可以对输入的信号的上升沿,下降沿或者双边沿进行捕获,通常用于测量输入信号的脉宽、测量 PWM 输入信号的频率及占空比。
        输入捕获的工作原理比较简单,在输入捕获模式下,当相应的 ICx信号检测到跳变沿后,将使用捕获/比较寄存器(TIMx_CCRx)来锁存计数器的值。简单的说就是通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄存(TIMx_CCRx)里面,完成一次捕获。同时还可以配置捕获时是否触发中断/DMA 等。

         在stm32中文手册中有如下图(也就是通用定时器的结构图):

在通用定时器中,输入捕获主要用到以上部分,STM32的每个通用定时器都有4个输入捕获的通道,分别是TIMx_CH1、TIMx_CH2、TIMx_CH3、TIMx_CH4。我们可以在输入滤波器和边沿检测器中设置我们需要捕获的是上升沿还是下降沿,假设我们需要捕获上升沿,则当滤波器和边沿检测器捕获到上升沿后,CNT计数器中的值会加1,同时捕获/比较寄存器中会锁存计数器的值。

二、输入捕获配置步骤

接下来我们介绍下如何使用库函数对通用定时器的输入捕获进行配置 。这个也是在编写程序中必须要了解的。其实输入捕获和前面定时器中断一样也是通用定时器的一个功能,因此还是要用到定时器的相关配置函数,具体步骤如下:(定时器相关库函数在stm32f10x_tim.c和
stm32f10x_tim.h文件中)。
(1)使能定时器及端口时钟,并设置引脚复用器映射和引脚模式等(以PA0为例)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);

其中需要将PA0端口进行复用,复用为TIM5的通道1,所以我们需要开启复用时钟,GPIOA时钟。

(2)初始化定时器参数,包含自动重装值,分频系数,计数方式等

voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef*TIM_TimeBaseInitStruct);

 (3)设置通用定时器的输入捕获参数,开启输入捕获功能

void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);

其中TIM_ICInitTypeDef结构体中的成员大致意思为:

typedef struct
{
uint16_t TIM_Channel; //通道
uint16_t TIM_ICPolarity; //捕获极性
uint16_t TIM_ICSelection;//映射
uint16_t TIM_ICPrescaler;//分频系数
uint16_t TIM_ICFilter; //滤波器长度
} TIM_ICInitTypeDef;
如果我们需要配置TIM5的通道1为输入捕获功能,并且为上升沿捕获。不分频、直接映射到TI,可以如下配置:

 TIM_ICInitTypeDef TIM_ICInitStructure;

TIM_ICInitStructure.TIM_Channel=TIM_Channel_1; //通道1
TIM_ICInitStructure.TIM_ICFilter=0x00; //滤波
TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;//捕获
极性
TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1; //分频系数
TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;//
直接映射到TI1
TIM_ICInit(TIM5,&TIM_ICInitStructure);

 (4)开启捕获和定时器溢出(更新)中断

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE)

(5)设置定时器中断优先级,使能定时器中断通道 

 NVIC初始化库函数是NVIC_Init()

(6)编写定时器中断服务函数 

TIM5_IRQHandler
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
TIM_SetCounter(TIM5,0); //定时器初值为0

(7)使能定时器 

 void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

 下面有一个输入捕获大致代码(以判断但双击按键为例):

void Tim_Input_Capture(u16 per,u16 psc)
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStruct;
	TIM_ICInitTypeDef  TIM_ICInitStruct;
	NVIC_InitTypeDef  NVIC_InitStruct;
	/*1、打开外设时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO , ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);

	/*2、配置GPIO*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
	GPIO_Init(GPIOA, &GPIO_InitStruct);

	/*3、配置定时器*/
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period = per;
	TIM_TimeBaseInitStruct.TIM_Prescaler = psc;
	TIM_TimeBaseInit(TIM5, &TIM_TimeBaseInitStruct);

	/*4、配置输入捕获*/
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStruct.TIM_ICFilter = 0x0;
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_ICInit(TIM5, &TIM_ICInitStruct);

	/*5、配置定时器中断*/
	TIM_ITConfig(TIM5, TIM_IT_Update | TIM_IT_CC1, ENABLE);

	/*6、配置NVIC*/
	NVIC_InitStruct.NVIC_IRQChannel = TIM5_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStruct);

	/*7、使能定时器*/
	TIM_Cmd(TIM5, ENABLE);
}

服务中断函数:

void TIM5_IRQHandler(void)
{
	if((input_state & NEXT_RISING ) != SET)
	{
		if(TIM_GetITStatus(TIM5, TIM_IT_Update) == SET)
		{
			if(input_state & NEXT_FALLING)//捕获到上升沿
			{
				if((input_state & 0x3F) == 0x3F)//如果溢出次数超出阈值
				{
					input_value = 0xFFFF;
					input_state |= NEXT_RISING;
				}
				else
					input_state++;
			}
		}
		if(TIM_GetITStatus(TIM5, TIM_IT_CC1) == SET)
		{
			if(input_state & NEXT_FALLING)//捕获到下降沿
			{
				//获取捕获到的值
				//改为上升沿捕获
				input_value = TIM_GetCapture1(TIM5);
				TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Rising);
				input_state |= NEXT_RISING;
			}
			else//捕获到上升沿
			{
				//清零input_state和input_value
				//关闭定时器
				//清空当前计数值
				//将下一次捕获改为下降沿捕获
				//标志下一次捕获下降沿
				//打开定时器
				input_state = 0;
				input_value = 0;
				TIM_Cmd(TIM5, DISABLE);
				TIM_SetCounter(TIM5, 0);
				TIM_OC1PolarityConfig(TIM5, TIM_ICPolarity_Falling);
				input_state |= NEXT_FALLING;
				TIM_Cmd(TIM5, ENABLE);
			}
		}
	}
	TIM_ClearITPendingBit(TIM5, TIM_IT_Update | TIM_IT_CC1);
}

更多推荐

C/C++算法入门 | 简单模拟

不爱生姜不吃醋⭐️如果本文有什么错误的话欢迎在评论区中指正与其明天开始,不如现在行动!文章目录🌴前言🌴一、害死人不偿命的(3n+1)猜想1.题目(PATB1001)2.思路3.代码实现🌴二、挖掘机技术哪家强1.题目(PATB1032)2.思路3.代码实现🌴总结🌴前言本文内容是关于C/C++算法入门的简单模拟题

3D模型格式转换工具HOOPS Exchange协助Epic Games实现CAD数据轻松导入虚幻引擎

一、面临的挑战EpicGames最为人所知的身份可能是广受欢迎的在线视频游戏Fortnite的开发商,但它也是虚幻引擎背后的团队,虚幻引擎是一种实时3D创作工具,为世界领先的游戏提供动力,并且也被电影电视、建筑、汽车、制造、模拟等领域采用。从很多方面来说,这种进展并不令人意外。由于视频游戏行业在渲染和可视化方面往往处于

Go基础语法:基本数据类型

3基本数据类型基本数据类型包括:整型、浮点型、布尔型、字符串。除以上基本类型之外,还有数组、切片、结构体、函数、map、通道等。3.1整型3.1.1整型整型分为:int8、int16、int32、int64,以及对应的无符号整型:uint8、uint16、uint32、uint64其中unit8对应其他语言中的byte

数据结构——图(图的存储及基本操作)

文章目录前言一、邻接矩阵法(顺序存储)1.无向图存储邻接矩阵算法2.有向图存储邻接矩阵算法二、邻接表法(图的链式存储结构)总结前言邻接矩阵法(图的顺序存储结构)1.1无向图邻接矩阵算法1.2有向图邻接矩阵算法邻接表法(图的一种链式存储结构)一、邻接矩阵法(顺序存储)定义:用一个一维数组存储顶点,一个二维数组存储边的信息

Mac专用投屏工具AirServer 7 .27 for Mac中文免费激活版

AirServer7.27forMac中文免费激活版是一款Mac专用投屏工具,能够通过本地网络将音频、照片、视频以及支持AirPlay功能的第三方App,从iOS设备无线传送到Mac电脑的屏幕上,把Mac变成一个AirPlay终端的实用工具。目前最新的AirServer7.2.7版本,支持macOSHighSierra

goaccess 日志分析 nginx

分析命令:goaccess-a-d-f/mnt/winshare/access-2023070112.log-pgoaccess.conf-o/mydata/nginx/html/2023070112_new.html分析日志时的参数goaccess使用参数详解-a开启UserAgent列表。开启后会降低解析速度-c在

高成本获客时代,企业如何通过营销自动化实现突围?

在数字化时代,随着市场竞争的不断升级,企业在获客方面面临了前所未有的挑战。不论是B端或C端的市场和运营部门纷纷寻求可降低获客成本的新运营路径,将有限的预算花在刀刃上。企业迫切需要寻求更加智能和高效的方式来吸引、转化和留住潜在客户,而营销自动化正是解决这些问题的利器。今天运营坛将和大家探讨获客和培育这两大核心。一、高成本

用低代码开发工具高效构建企业门户

企业信息门户EIP是指将各种应用系统、数据资源和互联网资源统一集中,根据每个用户使用特点和角色的不同,形成个性化的应用界面,并通过对事件和消息的处理、传输把用户有机地联系在一起。企业随着业务的发展,运作的复杂度也在不断加大,再加上各部门的业务量和业务的复杂度都在不断增加,可能已经建设了ERP、OA、考勤、合同、BPM、

阿里测开面试大全(一)附答案完整版

万字长文,建议收藏1什么是POM,为什么要使用它?POM是PageObjectModel的简称,它是一种设计思想,而不是框架。大概的意思是,把一个一个页面,当做一个对象,页面的元素和元素之间操作方法就是页面对象的属性和行为,所以自然而然就用了类的思想来组织我们的页面。一般一个页面写一个类文件,这个类文件包含该页面的元素

【Git】Git 变基(rebase)以及rebase和merge之间的区别

Git变基1.变基—rebase在Git中整合来自不同分支的修改主要有两种方法:merge以及rebase。在前面的文章中已经介绍了merge,这里我们来学习另一个指令rebase。变基的基本操作回顾之前在分支的合并中的一个例子,在该例子中,我们可以看到开发任务分叉到两个不同分支,又各自提交了更新。之前介绍过,整合分支

行为树的基本概念和C++库

一说明行为树是计算机科学、机器人技术、控制系统和视频游戏中使用的计划执行的数学模型。它们以模块化方式描述一组有限任务之间的切换。他们的优势来自于他们能够创建由简单任务组成的非常复杂的任务,而不用担心简单任务是如何实现的。行为树与分层状​​态机有一些相似之处关键区别在于行为的主要构建块是任务而不是状态。它易于人类理解,使

热文推荐