cancel
Showing results for 
Search instead for 
Did you mean: 

EXTI signal capture speed limitation

hermanv
Associate II
Posted on January 18, 2013 at 15:12

Hi all,

I am using a DiscoreryF4 board to develop a small application that counts pulses entering a specific pin. This is required to read the pulses from a field instrument that generates the pulses as some processes within the instrument occurs. Thus it is never a fixed number of pulses or a fixed frequency. All I need to do is count the number of pulses within a second in order to provide the results of the process within the instrument. I am using a signal generator so simulate the instrument that generates the pulses. Although it is a fixed frequency, it serves as a good enough simulation tool. The problem I experience is that I can only accurately count the pulses up to a frequency of 1.3MHz. At higher frequencies the values counted initially halves and then the processor halts. When decreasing the frequency after a halt occurred, the processor continues to operate again. Is there a maximum limit to the input frequencies that can be handled? Possibly the error occurs due to noise generated as part of this high input frequency that is affecting the processor or other components. I am posting the code used. Please comment if anyone spots mistakes that might be the cause of my problem.


static
void
init_exti_capture(
void
)

{

GPIO_InitTypeDef GPIO_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

TIM_OCInitTypeDef TIM_OCInitStructure;

EXTI_InitTypeDef EXTI_InitStructure;


__disable_irq();


/* SYSCFG clock enable */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);



/* GPIOC clock enable */

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);



/* TIM8 clock enable */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);



/* EXTI1 line 0 : pin (PA.01) configuration */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOA, &GPIO_InitStructure);


/* Connect EXTI Line1 to PA1 pin */

SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource1);


/* Configure EXTI Line1 */

EXTI_InitStructure.EXTI_Line = EXTI_Line1;

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;

EXTI_InitStructure.EXTI_LineCmd = ENABLE;

EXTI_Init(&EXTI_InitStructure);



/* Enable and set EXTI Line1 Interrupt to the lowest priority */

NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);



/* Enable the TIM8 global Interrupt */

NVIC_InitStructure.NVIC_IRQChannel = TIM8_UP_TIM13_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);


/* configure timebase for 1s */

TIM_TimeBaseStructure.TIM_Prescaler = (168 * 10) - 1;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseStructure.TIM_Period = 10 - 1;

TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;

TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0;


TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);


/* Channel 1 Configuration in Timing mode */

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;

TIM_OCInitStructure.TIM_Pulse = 0x0;


TIM_OC1Init(TIM8, &TIM_OCInitStructure);


/* Enable the TIM8 Update Interrupt */

TIM_ITConfig(TIM8, TIM_IT_Update, ENABLE);


TIM_Cmd(TIM8, ENABLE);


__enable_irq();


return
;

}

void
EXTI1_IRQHandler(
void
)

{


if
(EXTI_GetITStatus(EXTI_Line1) == SET)

{

/* increment as pulse detected */

EXTI_Capture_Rising_Cnt++;


EXTI_ClearITPendingBit(EXTI_Line1);

} 
/* end ''if (EXTI_GetITStatus(EXTI_Line1) == SET)'' */


return
;

}

The value of EXTI_Capture_Rising_Cnt is printed and cleared every 1 second as part of the main loop. Also see attached system_stm32f4xx.c file for clock and PLL configuration. Thanks guys, H #exti #timer #timer
10 REPLIES 10
Posted on January 18, 2013 at 15:41

Well you'd want to use a timer to count the pulses. If you continually interrupt the processor you can quite quickly eat 100 cycles, and saturate it. I'd avoid anything above a few 100 KHz.

The inputs do have a resynchronizer on them which has nyquist sampling properties, but not at the frequency you suggest.

Use a timer, integrate over a 10 or 100 ms period. If precision is important sample the CNT via DMA triggered by another timer, and do the computation in a HT/TC interrupt off the DMA.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
hermanv
Associate II
Posted on January 21, 2013 at 09:45

Thanks for the response Clive.

I am not sure if I understand you correctly. Do I need to use the input signal as the clock for the TIMER and then use the CNT value as my result?

I also don't understand what you mean by integrate on 10 or 100ms.

Please explain,

Thanks,

H
hermanv
Associate II
Posted on January 21, 2013 at 11:34

Hi Clive,

I configured TIM5 as an up-counter and connected the input signal to TI2. I poll the value every 1 second. I managed to measure frequencies up to 42MHz (don't have anything that can generate a faster pulse). Seems accurate enough for what we need so did not try the DMA route yet, but might do it later.

Thanks for pointing me in the right direction.

H
Posted on January 21, 2013 at 16:18

I also don't understand what you mean by integrate on 10 or 100ms.

You are integrating over a second, a 16-bit counter will exceed it's limit at >65 KHz, you could daisy chain the counter, use a 32-bit counter, or integrate over shorter periods.

Some signals change frequency over a second if modulated, where you need to measure such you'll have to sample more frequently to observe that.

Also remember clock signals generated by the chip are synchronous to each other, independent sources will drift with respect to each other.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
touatimohamed
Associate II
Posted on March 01, 2013 at 08:59

Hi van_wyk.herman

I configured the timer 5 in input capture to measure frequency but doesn't work.

Can you help me please.

/* Private function prototypes -----------------------------------------------*/

void TIM_Config(void);

int main(void)

{

 TIM_Config();

 TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;

  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_ICInit(TIM5, &TIM_ICInitStructure);

  /* TIM enable counter */

  TIM_Cmd(TIM5, ENABLE);

  /* Enable the CC2 Interrupt Request */

  TIM_ITConfig(TIM5, TIM_IT_CC2, ENABLE);

  while (1);

}

void TIM_Config(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  NVIC_InitTypeDef NVIC_InitStructure;

  /* TIM1 clock enable */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);

  /* GPIOA clock enable */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

  /* TIM1 channel 2 */

  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_1;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Connect TIM pins  */

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM5);

  /* Enable the TIM1 global Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

*************************************

void TIM5_IRQHandler(void)

{

  if(TIM_GetITStatus(TIM5, TIM_IT_CC2) == SET)

  {

    /* Clear TIM Capture compare interrupt pending bit */

    TIM_ClearITPendingBit(TIM5, TIM_IT_CC2);

    if(CaptureNumber == 0)

    {

      /* Get the Input Capture value */

      IC3ReadValue1 = TIM_GetCapture2(TIM5);

      CaptureNumber = 1;

    }

    else if(CaptureNumber == 1)

    {

      /* Get the Input Capture value */

      IC3ReadValue2 = TIM_GetCapture2(TIM5);

      /* Capture computation */

      if (IC3ReadValue2 > IC3ReadValue1)

      {

        Capture = (IC3ReadValue2 - IC3ReadValue1);

      }

      else if (IC3ReadValue2 < IC3ReadValue1)

      {

        Capture = ((0xFFFF - IC3ReadValue1) + IC3ReadValue2);

      }

      else

      {

        Capture = 0;

      }

      /* Frequency computation */

      TIM5Freq = (uint32_t) SystemCoreClock / Capture;

      CaptureNumber = 0;

    }

  }

}

Posted on March 01, 2013 at 13:23

Not working how exactly?

Wouldn't you want to configure the timebase to something appropriate for your signal?

This math is wrong

        Capture = ((0xFFFF - IC3ReadValue1) + IC3ReadValue2);

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
touatimohamed
Associate II
Posted on March 11, 2013 at 09:47

Hi , 

this code doesn't measure high frequency but measure low frequency like 300 khz.

Posted on March 11, 2013 at 14:47

Did you read any responses in this thread?

You're not going to be able to use interrupts at high rates. So instead of trying to measure deltas against a fast clock (period) you should measure your signal as it counts over time, sampling with a slow clock (frequency), ie integrate.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
touatimohamed
Associate II
Posted on March 14, 2013 at 11:15

Hi,

Can you tell me how to do this.