TIM input capture - STM32

TIM input capture - STM32

IC (Input Capture)
In the input capture mode, when the channel input pin has a specified level jump, the current CNT value will be latched into the CCR, which can be used to measure the frequency, duty cycle, and pulse of the PWM waveform. Parameters such as interval, level duration, etc.
Each advanced timer and general-purpose timer has 4 input capture channels that can be configured as PWMI mode, and the frequency and duty cycle can be measured at the same time. The master-slave trigger mode can be used to realize the hardware automatic measurement
insert image description here
output The difference between comparison and input capture:
output comparison, the pin is an output port; input capture, the pin is an input port.
The output comparison is to perform the output action according to the size relationship between the CNT and the CCR; the input capture is to receive the input signal and perform the action of latching the CNT to the CCR.
insert image description here
insert image description here
insert image description here
Generally, we can first determine the ARR according to the resolution requirements; for example, 1% of the resolution is enough, then the ARR is 100-1, so that the PSC determines the frequency, and the CCR determines the duty cycle.
insert image description here
Step 1: RCC turns on the clock, and turns on the clocks of GPIO and TIM
Step 2: Initialize GPIO, configure GPIO as input mode, generally choose pull-up input or floating input mode
Step 3: Configure time base unit, let CNT The counter is driven by the internal clock to run automatically
. The fourth step is to configure the input capture unit. Including parameters such as filter, polarity, direct channel or cross channel, and frequency divider; it can be configured uniformly with a structure. The fifth step is to
select the trigger source of the slave mode. Select the trigger source as TI1FP1, call a library function here, and just give a parameter
. The sixth step is to select the operation to be performed after the trigger. To execute the Reset operation, it is enough to call a library function here. Call
the TIM_Cmd function to start the timer.

When we need to read the frequency of the latest cycle, we can directly read the CCR register, and then calculate it according to fc/N.
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
test frequency

#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
	//第一步开启时钟,初始化RCC,选择TIM2
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);	
	//设置输出PWM的GPIO端口
		//使能GPIOA的时钟 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	
	//GPIOA模式初始化
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
		
	//第二步选择时基单元的时钟,选择内部时钟,选择TIM2
	TIM_InternalClockConfig(TIM3);
	
	//第三步配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频系数 1分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//计数的模式 向上计数
	//频率为1KHz,占空比为50%的PWM波形
	//计数器溢出频率:CK CNT_OV = CKCNT /(ARR + 1)= CK PSC /(PSC + 1)/(ARR +1)
	//配置定时为1s,则CK CNT_OV=1;CKCNT=72MHz=72000000;
	TIM_TimeBaseInitStruct.TIM_Period = 65536 - 1;//周期,ARR自动重装器的值 范围0~65536 设置为最大值,防止溢出
	TIM_TimeBaseInitStruct.TIM_Prescaler = 72 - 1;//PSC预分频器的值 范围0~65536 最后1Mhz
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; //重复计数器的值 高级计数器才有
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
	
	//第四步,配置输入捕获单元。包括滤波器、极性、直连通道还是交又通道、分频器这些参数
	TIM_ICInitTypeDef TIM_ICInitStruct;
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//选择通道 选择TIM3的通道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);
	
	//第五步,选择从模式的触发源。触发源选择为TI1FP1,这里调用一个库函数,给一个参数就行了
	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
	
	//第六步,选择触发之后执行的操作。执行Reset操作,这里也是调用一个库函数就行了
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
	
	//调用TIM_Cmd函数,开启定时器
	TIM_Cmd(TIM3,ENABLE);
}

//函数返回的是最新"个周期的频率值,单位是Hz
//Freq = CK_PSC / (PSC + 1) / (ARR + 1) 
//CK_PSC= 72MHz    PSC + 1 =100
uint32_t IC_GetFreq(void)
{
	return 10000000/(TIM_GetCapture1(TIM3)+1);
}

insert image description here

#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
	//第一步开启时钟,初始化RCC,选择TIM2
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);	
	//设置输出PWM的GPIO端口
		//使能GPIOA的时钟 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);	
	//GPIOA模式初始化
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
		
	//第二步选择时基单元的时钟,选择内部时钟,选择TIM2
	TIM_InternalClockConfig(TIM3);
	
	//第三步配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频系数 1分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//计数的模式 向上计数
	//频率为1KHz,占空比为50%的PWM波形
	//计数器溢出频率:CK CNT_OV = CKCNT /(ARR + 1)= CK PSC /(PSC + 1)/(ARR +1)
	//配置定时为1s,则CK CNT_OV=1;CKCNT=72MHz=72000000;
	TIM_TimeBaseInitStruct.TIM_Period = 65536 - 1;//周期,ARR自动重装器的值 范围0~65536 设置为最大值,防止溢出
	TIM_TimeBaseInitStruct.TIM_Prescaler = 72 - 1;//PSC预分频器的值 范围0~65536 最后1Mhz
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; //重复计数器的值 高级计数器才有
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
	
	//第四步,配置输入捕获单元。包括滤波器、极性、直连通道还是交又通道、分频器这些参数
	TIM_ICInitTypeDef TIM_ICInitStruct;
	
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//选择通道 选择TIM3的通道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);//在函数里,会自动把剩下的一个通道初始化成相反的配置
//	TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;//选择通道 选择TIM3的通道1
//	TIM_ICInitStruct.TIM_ICFilter = 0xF;//用来配置输入捕获的滤波器。数越大滤波效果越好
//	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;//上升沿触发
//	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//配置分频器,不分频
//	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_IndirectTI;//配置数据选择器,交叉输入
//	TIM_ICInit(TIM3,&TIM_ICInitStruct);
	
	//第五步,选择从模式的触发源。触发源选择为TI1FP1,这里调用一个库函数,给一个参数就行了
	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
	
	//第六步,选择触发之后执行的操作。执行Reset操作,这里也是调用一个库函数就行了
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
	
	//调用TIM_Cmd函数,开启定时器
	TIM_Cmd(TIM3,ENABLE);
}

//函数返回的是最新"个周期的频率值,单位是Hz
//Freq = CK_PSC / (PSC + 1) / (ARR + 1) 
//CK_PSC= 72MHz    PSC + 1 =100
uint32_t IC_GetFreq(void)
{
	return 10000000/(TIM_GetCapture1(TIM3)+1);
}

//获取占空比
//Duty = CCR / (ARR + 1)
uint32_t IC_GetDuty(void)
{
	//高电平的计数值存在CCR2里;整个周期的计数值存在CCR1里;用CCR2/CCR1,就能得到占空比了
	return (TIM_GetCapture2(TIM3)+1)*100/(TIM_GetCapture1(TIM3)+1);//范围是0%~100%
}

Guess you like

Origin blog.csdn.net/qq_45159887/article/details/130474564