cancel
Showing results for 
Search instead for 
Did you mean: 

How to get 4 channel input capture values from stm32f407 ?

isar�
Associate II
uint32_t IC2Value,Frequency,miliseconds;
float DutyCycle;
 
 
static void TIM2_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  TIM_ICInitTypeDef  TIM_ICInitStructure;  
  /* TIM2 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
 
  /* GPIOB clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //Change here, to GPIOA 
 
  /* TIM2 chennel2 configuration : PA1 */
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2 | GPIO_Pin_3  ;  //Change here, to pin 10
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;
  GPIO_Init(GPIOA, &GPIO_InitStructure);   //Change to GPIOA
 
  /* Connect TIM pin to AF2 */
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM2); //And change to pin 1
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM2);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_TIM2);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM2);
  /* Enable the TIM2 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
 
   /* --------------------------------------------------------------------------- 
    TIM2 configuration: PWM Input mode
     The external signal is connected to TIM2 CH2 pin (PB.03)
     TIM2 CCR2 is used to compute the frequency value 
     TIM2 CCR1 is used to compute the duty cycle value
 
    In this example TIM2 input clock (TIM2CLK) is set to APB1 clock (PCLK1), since
    APB1 prescaler is set to 1.
      TIM2CLK = PCLK1 = HCLK = SystemCoreClock
 
    External Signal Frequency = SystemCoreClock / TIM2_CCR2 in Hz.
    External Signal DutyCycle = (TIM2_CCR1*100)/(TIM2_CCR2) in %.
  Note: 
  SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f0xx.c file.
  Each time the core clock (HCLK) changes, user had to call SystemCoreClockUpdate()
  function to update SystemCoreClock variable value. Otherwise, any configuration
  based on this variable will be incorrect.
  --------------------------------------------------------------------------- */
 
  
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter = 0x0;
 
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; 
	TIM_ICInit(TIM2,&TIM_ICInitStructure);
	
 
 
	TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);
	
  /* Select the TIM2 Input Trigger: TI2FP2 */
  TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);
 
  /* Select the slave Mode: Reset Mode */
  TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
  TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);
 
  /* TIM enable counter */
  TIM_Cmd(TIM2, ENABLE);
	
 
  /* Enable the CC2 Interrupt Request */
   TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
}
//And the Interrupt code: //I have changed nothing in it
 
void TIM2_IRQHandler(void)
{
  /* Clear TIM2 Capture compare interrupt pending bit */
  TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
 
  /* Get the Input Capture value */
  IC2Value = TIM_GetCapture2(TIM2);
 
  if (IC2Value != 0)
  {
    /* Duty cycle computation */
    DutyCycle = (float)(TIM_GetCapture1(TIM2) * 100) / IC2Value;
 
    /* Frequency computation */
    Frequency = SystemCoreClock / IC2Value;
		
		miliseconds = DutyCycle*200;
  }
  else
  {
    DutyCycle = 0;
    Frequency = 0;
  }
}
 
 
int main()
{
	
	TIM2_Config();
	
	while(1){
		
		TIM2_IRQHandler();
		
 
}
	
	}
 

I'm trying to get frequency and duty cycle values from input capture mode.It is working for 1 channel but I need 4 channel. So how can I get 4 channel input capture values from stm32f407 ?

Here is my code which works properly: 

4 REPLIES 4

The method uses two channels paired, CH1 and CH2

For each signal you need to measure you will need to use a different TIM peripheral, as each has a single counting element, and is being reset. CH3/4 are not usable in this fashion.

The alternative is to use a single TIM, but have it free run with a maximal count, and use Input Capture for each channel, interrupting for both rising and falling edge, and reading the individual channel's CCRx latched value of the CNT (count), and then delta the measurements. With 3 measurements A, B, C, the period is C-A, the high time B-A and low time C-B

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
isar�
Associate II

but when use different timer for example Tımer 3 , all values are incorrect. Tımer 2 is 32 bit timer and Tımer 3 is 16 bit. Is it about it?

That depends on the ratio of the measured signal's frequency/pulse width and the timer's clock. If the input signal is too slow and the 16-bit timer overflows (maybe several times), then of course you get incorrect values. You then have to count the overflows in an interrupt, and/or use an appropriate prescaler (at the cost of decreased resolution).

JW

isar�
Associate II

It is 50hz signal, it is too slow.Should I increase the TIM_ICPrescaler ? Is it going to enough for getting correct value?