☰
STM32 定时器 输入捕获
2026/10/19 6:45:44 网站建设 项目流程

用于测频率测占空比

IC(Input Capture)输入捕获

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

如上图,左下角的三个输入连接在一个异或门,当3个输入引脚有任何一个有电平翻转时,输出引脚就产生一次电平反转,输出通过数据选择器,到达输入捕获通道1,数据选择器可以选择上面或者下面一个(不通过异或门),设计这个异或门是为三相无刷电机服务的

无刷电机有3个霍尔传感器检测转子位置,可以根据转子的位置进行换相,有了这个异或门,3个通道就可以连接上无刷电机的霍尔传感器。

输入滤波、边沿检测(可以选择高电平触发、低电平触发,当出现指定的电压时,边沿检测电路就会触发后续电路执行动作)

有两套输入滤波、边沿检测电路,通道一可以输出TI1FP1和TI1FP2(去了IC2),通道二也可以输出TI2FP1(去了IC1)和TI2FP2。可以灵活切换输入,可以把一个引脚的输入映射到两个捕获单元,第一个捕获通道,使用上升沿触发,用来捕获周期,第二个通道,使用下降沿触发,捕获占空比,两通道同时对一个引脚进行捕获,就可以同时测量频率和占空比。

通道3、4也是一样,可以选择各自独立连接或者进行交叉。

TRC信号,在图上部分连接

预分频器:对输入的信号分频,分频后的信号触发捕获电路进行工作

每来一个触发信号,CNT的值就会向CCR转运一次,转运的同时发生一个捕获事件,该事件会在状态寄存器置标志位,同时也可以产生中断,CCR捕获到的置就是公式里的N

CNT清零可以使用主从触发模式来自动完成。

CCMR1寄存器里的ICF位可以控制滤波器的参数

滤波器工作原理在CCMR1寄存器一节

边沿检测器捕获上升沿或者下降沿

用CCER寄存器里的CC1P位,可以选择极性

最终得到TI1FP1触发信号,通过数据选择器

应当还有一条一样的电路,得到TI1FP2的触发信号,连通到通道2(IC2)

CC1S位可以对数据选择器进行选择

ICPS位可以配置分频器。选择不、2、4、8分频

CC1E位控制输出使能或失能

为方便下一次计数,将CNT里的值捕获到CCR里面后,清零CNT,方便下一次捕获

如何自动清零CNT

TI1FP1信号和TI1的边沿信号都可以通向从模式控制器,从模式里面有电路可以自动完成CNT清零

频率测量

上图是一个频率逐渐降低的方波波形,左边频率最高,右边最低,只有高低电平的数字信号,STM32只能测量数字信号,如果要测量正弦波,那则还需要搭建一个信号预处理电路(最简单的就是用运放搭建一个比较器)将正弦波转换为数字信号,再输入给STM32即可。如果测量的电压信号非常高,还要考虑隔离问题,比如隔离放大器,电压互感等元件,隔离高压端和低压端,保证电路安全。

频率测量方法

测周法:用已知的标准频率fc的计次时钟来驱动计数器,计算连续的两个上升沿之间的间隔时间,从一个上升沿开始计,计数器从0开始一直计到下一个上升沿,停止,计一个数的时间是1/fc,计N个数,时间是N/fc,N/fc是周期,fc/N则为周期。

  • 测频法适合测量高频信号,测量结果更新慢,数值相对稳定
  • 测周法适合测量低频信号,测量结果更新快,数值跳变快波动大
  • 存在正负1误差
    • 测频法,在闸门时间内,可能有的周期信号不完整,比如在最后的时间,周期才出现一半,闸门时间就到了
    • 测周法,在最后时刻,一个数计到一半,周期就结束了
    • 要减小误差,就要增大N的值

结合两个公式将N消掉,得到两个方法误差相同时的频率

中界频率:当待测信号小于中界频率时,测周法误差更小,当待测信号大于中界频率时,测频法误差更小。

总结输入捕获基本结构

这个结构只使用了1个通道,只能测频率

注意:只有通道CH1、CH2可以使用从模式自动清零CNT,通道CH3、CH4只能开启捕获中断来手动清零,比较消耗软件资源。

PWMI基本结构

PWMI模式,使用了两个通道捕获一个引脚,可以同时测量周期和占空比。

TI1FP1配置为上升沿触发,触发CCR1捕获CNT值(测量周期)和清零CNT。

TI1FP2配置为下降沿触发,触发CCR2捕获CNT值。可以测量到高电平持续的时间,计算占空比。

测频法代码实现

使用计数器,每来一个上升沿,计次加1,再用定时器,定一个1s的定时中断,在中断里,每隔1s取计数器的值,同时清零计次,为下一次做准备。

输入捕获测频率 代码实现

产生PMW波

PSC和ARR都可以调节频率,但是占空比=CCR/(ARR+1),通过调节ARR调节频率还会影响到占空比因此:

先固定ARR,用PSC决定频率,CRR控制占空比

//用于单独设置PSC的值,TIM_PSCReloadMode指定重装模式 /** TIM_PSCReloadMode的值可以是 TIM_PSCReloadMode_Update: The Prescaler is loaded at the update event.预分频器在更新事件重装,周期结束时切断 TIM_PSCReloadMode_Immediate: The Prescaler is loaded immediately.预分频器立即重装,可能在值改变时产生切断波形的现象,比如一个周期还没完,就直接切断了 **/ void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);

时钟源频率为72Mhz

频率 Freq = 时钟源频率 / (PSC+1)/(ARR+1)
占空比 Duty = CCR /(CCR+1)

IC输入捕获配置

书写初始化函数

  1. RCC,开启GPIO和TIM时钟
  2. GPIO初始化,配置GPIO为输入模式(一般选择上拉或者浮空输入)
  3. 配置时基单元
  4. 配置输入捕获单元(包括滤波器、极性、直连通道还是交叉通道、分频器)
  5. 选择从模式的触发源(选择为TI1FP1)
  6. 选择触发之后要执行的操作,执行Reset
  7. 最后调用TIM_Cmd函数,启动定时器

相关函数学习

//初始化IC,一次只能配一个通道,四个IC通道共用这个函数 void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct); /** TIM_ICInitStructure结构体参数解释 TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //选择配置定时器通道1 TIM_ICInitStructure.TIM_ICFilter = 0xF; //输入滤波器参数,可以过滤信号抖动 TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //极性,选择为上升沿触发捕获 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //捕获预分频,选择不分频,每次信号都触发捕获 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //输入信号交叉,选择直通,不交叉 **/ //可配置两个通道,把外设电路配置成PWMI模式 void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct); //给输入捕获结构体赋初始值 void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct); //选择输入触发源TRGI(从模式的触发源选择) void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource); //选择输出触发源TRGO(主模式输出的触发源) void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource); //选择从模式(从模式的选择) void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode); //分别单独配置通道1、2、3、4的分频器 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只写,TIM_SetCompare1写入 //输入捕获模式下,CCR只读,TIM_GetCapture1读 //分别写入4个通道的CCR void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1); void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2); void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3); void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4); //分别读取4个通道的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);

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询