stm32 input capture

1. Introduction to Input Capture

 

  • In addition to the basic timers TIM6 and TIM7, STM32F1 has input capture capabilities.
  • Input capture captures the rising, falling or bilateral edges of the input signal. It is often used to measure the pulse width of the input signal, the frequency and duty cycle of the PWM input signal.
  • In input capture mode, when the corresponding ICx signal detects a jump edge, the capture/comparison register (TIMx_CCRx) is used to lock the value of the counter.

TIMx_CHx (independent channel of timer)

By detecting TIMx_ Edge signal on CHx, when the edge signal jumps (such as up/down edge), will be current Timer value (TIMx_CNT) Store in the capture/compare register (TIMx_CCRx) of the corresponding channel to complete a capture. You can also configure whether interrupts/DMA s are triggered during capture, etc.

2. Principles

  Picture Source: Strategies for developing stm32f1xx

Assuming that t1~t2 is a high level time to be measured, the timer works in the up counting mode.

Measurement method:

  1. First set the timer channel x to capture the rising edge, t1 captures the current CNT value at any time, then immediately zeroes the CNT, and sets channel x to capture the falling edge, so at t2 time, a capture event will occur again, and the CNT value at this time is recorded as CCRx2. Based on the counting frequency of the timer, the time of t1-t2 is calculated to obtain the high-level pulse width.
  2. N times of timer overflow may occur in t1-t2 time, so it is necessary to handle the timer overflow to prevent the measurement data from inaccurate due to the overflow of too long high level time. The number of CNT counts equals: N*ARR+CCRx2
  3. Duration of high level (t1 to t2)=   Number of CNT Counts   *  The counting period of the CNT.
  4. 16-bit automatic overload counter (CNT).

3. Code

Conceptual supplement:

  • The input capture channel is:   IC1/2/3/4
  • Universal timer has four TIMx_input channels CH1/2/3/4. These four channels are also commonly referred to as TI1/2/3/4

3.1, TIM5 initialization

#include "public.h"
/*
Fuction:
 

*/
// TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
// TIM Capture Comparison 1 Interrupt Source

/*
Annotation to practice

FuctionName:TIM5_CH1_Input_Init
Author/Writer: YI
Date:     2021/10/11
Fuction:  TIM5_CH1 input  Capture
InputName/Inpt Parameter:
Returned Value: NULL
Update/ amendant record:

*/
void TIM5_CH1_Input_Init(u16 arr,u16 psc)
{
	//  stm32f10x_tim.h Timer Initialization Definition
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	
	//  stm32f10x_tim.h Timer Input Capture Structure Definition
	TIM_ICInitTypeDef        TIM_ICInitStructure;
	
	// MISC.h Interrupt Nested Structure Initialization Definition
	NVIC_InitTypeDef         NVIC_InitStructure;
	
	// Stm32f10x_ Gpio.h GPIO Initialization Structure Definition
	GPIO_InitTypeDef         GPIO_InitStructure;
	
	//  Input capture is a function of the universal timer, so you need to enable the corresponding timer clock
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
	
	// Measurement of Pulse Width of Input Signal Using CH1 Channel of TIM5
	// The corresponding pin for the CH1 channel of TIM5 is PA0, so to enable the GPIOA port clock 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	//  They use PA0 to measure the high-level time of the input signal, so they need to configure PA0 as a drop-down input mode.
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;       // Pin Settings
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // Drop-down Input
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	// Set the timer auto overload count cycle value to update to the shadow register when the event occurs. The range can be set from 0 to 65535.
	TIM_TimeBaseInitStructure.TIM_Period = arr;     // Automatic Value Timer Cycle
	
	//  The prescaler factor of the timer through which the output of the clock source is the timer clock
	//  Set the range of values: 0-65535, because the division factor is a divisor, the denominator cannot be 0, so it will automatically add 1, and finally achieve 1-65536 frequency division
	TIM_TimeBaseInitStructure.TIM_Prescaler = psc;  // division factor
	
	// Clock frequency dividing factor, set timer clock CK_INT frequency to digital filter sampling clock frequency division ratio.
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;  // clock division
	
	//  Commonly used are the up count mode (TIM_CounterMode_Up) and the down count mode (TIM_CounterMode_Down).
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //  Timer counting method
	
	TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);	
	
	//  Enter capture channel settings, universal timer up to 4 channels each, if channel 1 of TIM5 is used, parameter TIM_Channel_1.
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;  // Channel 1
	
	// Filter length setting, no filter used, parameter 0. 
	// If we need to configure channel 1 of TIM5 for input capture and capture for rising edge, no crossover, direct mapping to TI
	TIM_ICInitStructure.TIM_ICFilter = 0x00;          //  Wave filtering
	
	// Effective capture polarity settings for the input signal, starting to capture the rising edge of the input signal with the parameter TIM_ICPolarity_Rising,
	// If descent edge capture is used, the parameter is TIM_ICPolarity_Rising
	// Set channel capture polarity function separately, if channel 1 capture polarity of TIM5 is to be modified to fall along
	//  TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising);
	// This function can be interpreted as a generic function, TIM_OCxPolarityConfig(), where x is the channel.
	// TIM_can be called if the polarity operation is captured on channel 2 OC2PolarityConfig function.
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // Capture Polarity
	
	//  Set the crossover factor, which can be TIM_ICPSC_DIV1, TIM_ICPSC_DIV2, TIM_ICPSC_DIV4, TIM_ICPSC_DIV8,
	//  No frequency division, parameter TIM_ICPSC_DIV1.
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;       // division factor
	
	//  Mapping settings ICx can be mapped to two TIx (refer to timer block diagram)
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // Map directly to TI1
	TIM_ICInit(TIM5,&TIM_ICInitStructure);
	
	/*
	Timer overflow interrupt
	Detect high level pulse width of input signal
	The rise edge is captured once, then set to the drop edge, and the fall edge is captured once, that is, the high level pulse width
	If the high level pulse width is longer, the timer may overflow, overflow will not allow the calculated high level time, so turn on the timer overflow interrupt
	
	*/
	TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;           // Interrupt channel
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // Preemptive Priority
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        // Subpriority
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           // IRQ Channel Enabling
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM5,ENABLE);
}

Tags: stm32 STM32F103

Posted on Wed, 03 Nov 2021 12:48:43 -0400 by mystrymaster