当前位置:   article > 正文

STM32———定时器输入捕获功能_stm32定时器输入捕获

stm32定时器输入捕获

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一,输入捕获简介

  • IC(Input Capture)输入捕获
  • 输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中,可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数。
  • 每个高级定时器和通用定时器都拥有4个输入捕获通道 。
  • 可配置为PWMI模式,同时测量频率和占空比。
  • 可配合主从触发模式,实现硬件全自动测量。

在这里插入图片描述

  • 左侧为定时器输入捕获部分,右边为定时器输出比较部分。
  • 四个输入捕获和四个输出比较共用四个捕获/比较寄存器,它们的引脚也是共用的。
  • 同一定时器,捕获,比较功能不可同时使用。

工作流程

(STM32选用测周法测量)
信号从通道一进入,遇到输入滤波器和边沿检测器(每个通道有两组,分别输出TIxFP1,TIxFP2)输出TI1FP1和TI1FP2信号(TI1FP2输入至通道2中),输出信号经过数据选择器(可选择TI1FP1,也可选择通道二输入的TI2FP1),经过选择器的信号,再由预分频器进行分频(系数自由选择),然后从预分频器每输出一个信号,触发一次捕获事件(在状态寄存器置标志位,也可产生中断,我们可选择在中断中处理一些事情),同时CNT的值向CCR转运一次(CNT由内部标准时钟驱动,可用来计算信号周期)。

注:每次触发捕获信号时,我们都要清零CNT的值。(可通过主从触发模式完成)

关于滤波器
在这里插入图片描述
每经过N个信号为高电平,输出为高电平;N个信号为低电平,输出为低电平
采样系数越大,采样周期越大,N越大,数据越准确。

频率测量
在这里插入图片描述

  • 测频法:在闸门时间T内,对上升沿计次,得到N,则频率f_x=N / T (时间T内,每来一个上升沿,N+1)
    测频法适用于信号频率较高的情况,减少误差;若在信号频率较低时,当闸门时间T到达时,计数仍为0,这是测得频率为0,但真实频率不为0,产生误差。
    测频法测得为频率的均值,当在时间T内,频率发生改变时,测频法是这段时间的均值;且更新慢(每隔T更新一次),值比较平滑。

  • 测周法:两个上升沿内,以标准频率fc计次,得到N ,则频率f_x=f_c / N (两个信号上升沿之间,使用标准频率为fc计数器计次,计次为N;一个计数时间1/fc,N个计次时间为N/fc,即为信号周期)
    测周法适用于频率较低的情况,减少误差;若在信号频率较大时,在两个上升沿内,计数器并未完成一次计数,频率为0,产生误差。
    测周法测得为信号的实时频率,即两个上升沿之间的周期倒数。更新速度取决于信号频率,更新更快,但只测一个周期,结果值易受干扰。

  • 中界频率:测频法与测周法误差相等的频率点f_m=√f_c / T

PWM的频率通常很大,那为什么还是用测周法?
对于测周法而言
被测信号频率远低于标准信号频率时,被测信号脉冲很多(N很大),测周法得到的结果就很准确。
对于测频法而言
被测信号频率远高于标准信号频率(单位时间内计次的快慢)时,时间T内测得 的N就越大(N很大),测频法得到的结果就很准确。

主从触发模式

在这里插入图片描述

主模式:可以将定时器内部的信号映射到TRGO引脚,触发其他外设。
从模式:接收其他外设或自身外设的信号,执行自身定时器的运行,被别的信号所控制。、

触发源选择:选择从模式信号触发源的,选择指定的信号,得到TRGI,触发从模式,选择指定操作。

详细介绍查看手册

输入捕获基本结构

在这里插入图片描述
工作流程:
配置时基单元,PSC输出的频率(72MHZ/预分频系数)为标准频率,计数器开始自增。GPIO输入PWM信号,经过滤波器,边沿检测器(选择上升沿触发),每一个上升沿,输出一个信号TI1FP1,数据选择器选择TI1FP1为输入信号,经过预分频器,输出信号。CCR1读取CNT的值,并由从模式清零CNT,进入下一检测。

PWMI基本结构

在这里插入图片描述
工作流程基本一致,PWM信号经过边沿检测器,其中一个配置为下降沿触发,输出TI1FP2信号到通道二的数据选择器,选择其为输入信号,经过预分频器,输出信号。CCR2读取CNT的值,此为一个PWM周期中,保持高电平,CNT的计数。CCR2/CCR1=占空比。

二, 配置输入捕获功能

  • 第一步:开启时钟,打开GPIO,TIM时钟。
  • 第二步:GPIO初始化,配置为输入模式。
  • 第三步:配置时基单元,CNT在内部时钟(用作标准频率fc)的驱动下自增运行。
  • 第四步:配置输入捕获单元,包括滤波器,极性,直连通道还是交叉通道,分频器等(结构体配置)。
  • 第五步:选择从模式触发源触发源为TI1FP1。
  • 第六步:开启定时器。
    最后读取CCR寄存器,得到N,f=fc/N;
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);//结构体配置输入捕获单元的函数。(四个通道共用),结构体中有个参数选择通道。
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);//快速配置两个通道。
void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);//结构体赋初始值
void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);//选择输入触发源TRGI
void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);//选择主模式输出的触发源,TRGO
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);//选择从模式

/*单独配置四个预分频器的参数*/
void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);

/*分别读取四个CCR的值*/
uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

第一步:开启时钟

/* 时钟配置*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//配置定时器3时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//配置GPIOA的时钟
  • 1
  • 2
  • 3

我们捕获使用TIM3,输出PWM使用TIM2
上文介绍过,同一定时器捕获输出只能选择一个。

第二步:配置GPIO

/*初始化GPIO*/
	GPIO_InitTypeDef GPIO_InitStruct;//定义结构体变量
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;//选择PA6通道打开
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//扫描速率
	
	GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

第三步:配置时基单元

	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//选择时钟滤波频率为0
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//CNT向上计数
	TIM_TimeBaseInitStruct.TIM_Period=65536-1;//ARR,最大值防止计数溢出。
	TIM_TimeBaseInitStruct.TIM_Prescaler=72-1;//PSC,确定fc=1MHZ
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;//高级定时器的重复计数器
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);//初始化时基单元
	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

注:如果被测频率太低,一个PWM周期内,CNT的值会溢出;这时我们可以加大PSC的值,降低fc频率。
第四步:初始化输入捕获单元

/*初始化输入捕获*/
	TIM_ICInitTypeDef TIM_ICInitStruct;
	
	TIM_ICInitStruct.TIM_Channel=TIM_Channel_1;			//通道选择,选择TIM1,为通道1
	TIM_ICInitStruct.TIM_ICFilter=0xF;					输入滤波器参数,可以过滤信号抖动
	TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Rising;//极性选择,每次上升沿触发信号。
	TIM_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1;//捕获预分频,选择不分频,每次信号都触发捕获。
	TIM_ICInitStruct.TIM_ICSelection=TIM_ICSelection_DirectTI;//输入信号交叉,选择直通,不交叉
	TIM_ICInit(TIM3, &TIM_ICInitStruct);       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

第五步:触发源选择

/*选择触发源及从模式*/
	TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);					//触发源选择TI1FP1
	TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);					//从模式选择复位
																	//即TI1产生上升沿时,会触发CNT归零
  • 1
  • 2
  • 3
  • 4

第六步:定时器使能

/*TIM使能*/
	TIM_Cmd(TIM3, ENABLE);			//使能TIM3,定时器开始运行
  • 1
  • 2

获取结果

uint32_t IC_GetFreq(void)
{
	return 1000000 / (TIM_GetCapture1(TIM3)+1);		//测周法得到频率fx = fc / N,这里不执行+1的操作也可
}
  • 1
  • 2
  • 3
  • 4
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/832105
推荐阅读
相关标签
  

闽ICP备14008679号