STM32-TIM输入捕获

一、概述

IC(Input Capture)输入捕获

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

以下为输入捕获的框图,左边一共有4路输入通道,对于同一个定时器输入捕获与输出比较只能使用其中一个。这个异或门的输入接在了通道1,2,3端口,异或门执行逻辑是:当三个输入引脚的任何一个有电平翻转时,输出引脚就产生电平翻转,之后输出通过数据选择器,到达输入捕获通道1。当数据寄存器不选择异或门时,就没有用,设计这个异或门,其实还是为三相无刷电机服务的。

然后来到输入滤波器和边沿检测器,滤波器是滤除噪声的不会改变频率,边沿检测器是检测是上升沿还是下降沿。

接着,有两套电路,第一套是TI1FP1。第二套是TI1FP2,输入给通道2。这样交叉的目的之一是可以把一个引脚的输入,同时映射到两个捕获单元,这也是PWMI模式的经典结构,让第一个通道测量频率,第二个通道测量占空比。

接着,预分频器对输入频率进行分频。分频之后的触发信号就可以触发捕获电路进行工作,每来一个触发信号,CNT的值就会向CCR(捕获寄存器)进行转运一次。转运的同时会发生一个捕获事件,这个事件会在状态寄存器置标志位,同时也可以产生中断。

 二、频率测量

测频法、测周法,大于中界频率用测频法,小于则用测周法,所以这个测频法适合测频率高的,测周法适合测频率低的。

三、输入捕获结构

如下图:经过滤波器滤波后,一路TI1FP1可以通向触发从模式控制器,这个从模式里面,就有电路,可以自动完成CNT的清零。滤波器中ICF[3:0]值越大滤波越好。另一路走通道1作为输入捕获。

当TI1FP1信号出现上升沿时,会将CNT的值向CCR中转运。同时,TI1FP1也作为触发源选择的触发信号,当出现上升沿时使CNT的值变为初始值(这里时硬件自动控制)。肯定是将CNT的值向CCR中转运在前,CNT的值变为初始值在后。

1、主从触发模式

 主模式:可以将定时器内部的信号,映射到TRGO引脚,用于触发别的外设。

 从模式:是被动的,就是接收其他外设或者自身外设的一些信号用于控制自身定时器的运行。

 触发源选择:就是用来触发从模式的。

2、输入捕获基本结构



3、PWMI基本结构 

 

四、测PWM占空比和频率代码

接线图:

  • 用TIM2_CH1通道先生成PWM波形代码

PWM.c:

#include "stm32f10x.h"                  // Device header


void PWM_Init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	//1.配置时钟,用那个外设
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
 	GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;   //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//2.内部时钟配置
	TIM_InternalClockConfig(TIM2);
	
	//3.配置时基单元
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;     //滤波频率
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up; //计数方式,向上
	TIM_TimeBaseInitStruct.TIM_Period=100-1;                   //自动重装载寄存器ARR
	TIM_TimeBaseInitStruct.TIM_Prescaler=0;                     //预分频器
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;

	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
	
	
	//4.输出比较初始化
	TIM_OCStructInit(&TIM_OCInitStructure);            //要给结构体赋一个初始值,否则有可能出现错误
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;               //输出模式
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High ;     //CC1P输出极性,这里的High指的是REF有效电平为高电平输出
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;   //输出使能
	TIM_OCInitStructure.TIM_Pulse=0;                               //用来设置CCR
	TIM_OC1Init(TIM2,&TIM_OCInitStructure);
	
	//5.启动定时器
	TIM_Cmd(TIM2,ENABLE);
	

}

//设置CCR
void PWM_SetCompare1(uint16_t Compare)
{
	
       TIM_SetCompare1(TIM2,Compare);
	
}

//设置预分频器
void PWM_SetPrescaler(uint16_t Prescaler)
{
	  
		 TIM_PrescalerConfig(TIM2,Prescaler,TIM_PSCReloadMode_Immediate);
	
	
}

PWM.h:

#ifndef _PWM_H
#define _PWM_H


void PWM_SetCompare1(uint16_t Compare);

void PWM_Init(void);
void PWM_SetPrescaler(uint16_t Prescaler);

#endif
  • 测量PWM的频率和占空比的代码

利用测周法测PWM占空比和频率,利用TIM3_CH1输入捕获通道进行捕获A6引脚输入的信号。 

IC.c:

#include "stm32f10x.h"                  // Device header


//测周法测PWM占空比和频率

void IC_Init(void)
{ 
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_ICInitTypeDef  TIM_ICInitStruct;
	GPIO_InitTypeDef GPIO_InitStructure;
	//1.配置时钟,用那个外设
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
 	GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU;   
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//2.内部时钟配置
	TIM_InternalClockConfig(TIM3);
	
	//3.配置时基单元
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;       //滤波频率
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;   //计数方式,向上
	TIM_TimeBaseInitStruct.TIM_Period=65535-1;                   //自动重装载寄存器ARR
	TIM_TimeBaseInitStruct.TIM_Prescaler=72-1;                   //预分频器
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;

	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
	
	//4.初始化捕获单元
	TIM_ICInitStruct.TIM_Channel=TIM_Channel_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);
	
	TIM_PWMIConfig(TIM3,&TIM_ICInitStruct);
	
	//5.触发源选择TI1FP1
	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
	
	//6.配置TRGI中从模式
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
	
	//7.启动定时器
	TIM_Cmd(TIM3,ENABLE);
	
}

//测频率
uint32_t IC_GetFreq(void)
{
	
	return 1000000/(TIM_GetCapture1(TIM3)+1);
	
	
}

//测占空比
uint32_t IC_GetDuty(void)
{
	
	return (TIM_GetCapture2(TIM3)+1)*100 /(TIM_GetCapture1(TIM3)+1);
	
	
}

IC.h:

#ifndef _LC_H
#define _LC_H


void IC_Init(void);

uint32_t IC_GetFreq(void);

uint32_t IC_GetDuty(void);


#endif

 main.c:

#include  "stm32f10x.h"                  // Device header
#include  "OLED.h"
#include  "delay.h"
#include  "PWM.h"
#include  "lC.h"

uint16_t  i;

int main(void)
{
	
   OLED_Init();
	PWM_Init();
	
	IC_Init();
	
	OLED_ShowString(1,1,"Freq:00000Hz");
	OLED_ShowString(2,1,"Duty:00%");
	PWM_SetPrescaler(3600-1);   //频率Freq=72M/(PSC+1)/100
	PWM_SetCompare1(80);       //CCR/100  占空比
	while(1) 
	{
	  
		OLED_ShowNum(1,6,IC_GetFreq(),5);
		OLED_ShowNum(2,6,IC_GetDuty(),2);
		
	}
	
}

### STM32 输入捕获功能概述 输入捕获(Input Capture)是在微控制器中广泛应用的一种技术,主要用于测量外部信号的脉冲宽度或频率。对于STM32系列而言,这一特性允许设备捕捉特定事件的时间戳,从而能够精确计算时间间隔或是监测周期性波形的变化情况[^2]。 具体到硬件层面,STM32F4中的大多数定时器(除TIM6和TIM7外),都具备输入捕获能力。当检测到指定通道(TIMx_CHx)上的电平发生变化时——无论是上升沿还是下降沿,系统会自动记录此时计数器(TIMx_CNT)内的数值,并将其保存至相应的捕获/比较寄存器(TIMx_CCRx)[^3]。 ### 实现方法详解 为了利用好这项强大的工具,在实际编程过程中需要注意几个关键点: #### 配置GPIO端口 首先应当设置好用于接收外部信号的GPIO引脚为复用推挽输出模式,确保其能正确响应来自外界的高低电平变化。 ```c // 假设使用PA0作为输入捕获源 __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 复用推挽输出 GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); ``` #### 初始化定时器并开启输入捕获 接着要对选定的定时器进行初始化操作,这里以通用定时器为例说明如何启用输入捕获功能: ```c TIM_HandleTypeDef htim; htim.Instance = TIM2; htim.Init.Prescaler = 8399; /* 设置预分频系数 */ htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = 65535; if (HAL_TIM_IC_Init(&htim) != HAL_OK){ Error_Handler(); /* 错误处理函数 */ } /* 配置输入捕获参数 */ sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; // 边沿极性选择 sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; // 直接映射方式 sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; // 不做额外分频 sConfigIC.ICFilter = 0x0; // 数字滤波器关闭 if (HAL_TIM_IC_ConfigChannel(&htim,&sConfigIC,TIM_CHANNEL_1)!= HAL_OK){ Error_Handler(); // 错误处理函数 } ``` 上述代码片段展示了针对某一特定实例化对象`htim`的操作流程,包括但不限于设定工作模式、调整预分配比例以及指定期望获取的数据类型等细节部分。 #### 中断服务程序编写 最后一步则是创建一个合适的ISR来处理每次成功完成数据采集后的后续动作。每当有新的有效样本被收集起来之后,就会触发该回调机制执行相应逻辑判断与运算分析任务。 ```c void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if(htim->Instance==TIM2){ // 判断是否是由TIM2产生的中断请求 uint32_t ICvalue= __HAL_TIM_GET_COMPARE(htim,TIM_CHANNEL_1); // 获取捕获值 // 对获得的结果进一步加工... HAL_GPIO_TogglePin(LED_PORT, LED_PIN); // 可选:切换LED状态表示正在处理新数据 } } ``` 通过以上三个主要环节的努力配合,便可以顺利搭建起一套基于STM32平台下的高效可靠的输入捕获解决方案了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值