cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 Timer External Pulse counting

piotrek700
Associate
Posted on May 18, 2013 at 00:23

Since 4 day I'm trying write code which will be able to count external pulses. I tried to use encoder mode but i supposed that this work only with 2 quadrature encoders. I have only one pulse signal and i have no idea how to do it. Could you help me or show examples how to count external pulses using timer?

#counter #timer #off-topic #pulce
35 REPLIES 35
vimukthi_0123
Associate II
Posted on April 06, 2015 at 18:17

I cannot figure out why i do not get the external pulse values print in my USART. please help.

float x_dot;

void TIM3_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

  

  /* GPIOC clock enable */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

 

  /* TIM3 clock enable */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

  

  /* GPIOA Configuration: TIM3 CH1 (PD12) */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // Input/Output controlled by peripheral

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // Button to ground expectation

  GPIO_Init(GPIOD, &GPIO_InitStructure);

 

    /* Connect TIM3 pins to AF */

  GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);

  

  TIM_TimeBaseStructure.TIM_Period = 65535;

  TIM_TimeBaseStructure.TIM_Prescaler = 0;

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

  

  TIM_TIxExternalClockConfig(TIM4, TIM_TIxExternalCLK1Source_TI1, TIM_ICPolarity_Rising, 0);

  

  TIM_Cmd(TIM4, ENABLE);

}

int main()

{

char str[120];

SystemInit();

TM_DELAY_Init();

/* Initialize USART, TX: PB6 */

TM_USART_Init(USART1, TM_USART_PinsPack_2, 9600);

while(1){

/* Every 500ms */

if (TM_DELAY_Time() >= 500) {

/* Reset time */

TM_DELAY_SetTime(0);

x_dot = TIM_GetCounter(TIM4);

sprintf(str, ''x_dot- %f\r\n'', x_dot);

TM_USART_Puts(USART1, str);

}

}

}

Posted on April 06, 2015 at 20:02

I cannot figure out why i do not get the external pulse values print in my USART. please help.

I'm not using that library, inconsistent TIM3 and TIM4 references, but nothing that's obviously fatal. So what can you tell about what's happening via the debugger, and oscilloscope?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
vimukthi_0123
Associate II
Posted on April 07, 2015 at 17:39

hi clive1. thank you for responding. i have done a stupid mistake. have not called the TIM4_Configuration(); inside the ''main''. after i get values. 

my external signal is a frequency varying from around 30 to 200Hz for different motor speeds. its coming from my motor controller. i need the frequency value to then get the speed and use the speed to control my motor. 

now i get the frequency but for a particular motor speed frequency is not constant. it gives varying values on my usart. i cannot figure out the problem in my code. please help. thank you in advance.

float x;

int CaptureNumber = 0;

float counter;

float Time;

float freq;

void TIM4_Configuration(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;

TIM_ICInitTypeDef TIM_ICInitStructure;

  /* GPIOC clock enable */

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

 

  /* TIM4 clock enable */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

  

  /* GPIOA Configuration: TIM4 CH1 (PD12) */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // Input/Output controlled by peripheral

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // Button to ground expectation

  GPIO_Init(GPIOD, &GPIO_InitStructure);

 

    /* Connect TIM4 pins to AF */

  GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);

  

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);

//   //Time initialization

  TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //Control with dead zone.

  TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;  //Counter direction

  TIM_TimeBaseInitStructure.TIM_Prescaler = 84-1;   //Timer clock = sysclock /(TIM_Prescaler+1) = 2M

  TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;

  TIM_TimeBaseInitStructure.TIM_Period = 0xFFFF;

//Period = (TIM counter clock / TIM output clock) - 1 = 40Hz 

  TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;

  TIM_ICInitStructure.TIM_ICFilter = 0;

  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

  TIM_ICInit(TIM4,&TIM_ICInitStructure);

  TIM_Cmd(TIM4,ENABLE);

}

int main()

{

char str[120];

SystemInit();

TM_DELAY_Init();

/* Initialize USART, TX: PB6 */

TM_USART_Init(USART1, TM_USART_PinsPack_2, 9600);

TIM4_Configuration();

while (1) {

/* Every 500ms */

if (TM_DELAY_Time() >= 500) {

/* Reset time */

TM_DELAY_SetTime(0);

if(TIM_GetFlagStatus(TIM4,TIM_FLAG_CC1)==SET)

{

TIM_ClearFlag(TIM4,TIM_FLAG_CC1);

if(CaptureNumber == 0)

{

counter = TIM_GetCapture1(TIM4);  //The first capture

CaptureNumber = 1;

}

else if(CaptureNumber == 1)  //Treatment of second capture

{

if(TIM_GetFlagStatus(TIM4,TIM_FLAG_Update) != SET)//Treatment of two capture no overflow occurs

{

Time = TIM_GetCapture1(TIM4);

Time = Time - counter;

}

else

{

TIM_ClearFlag(TIM4,TIM_FLAG_Update);   //The update event

Time = 0xFFFF - counter + TIM_GetCapture1(TIM4)+1;  //If the calculation mode update events

}

CaptureNumber = 0;

if(Time!=0)

{

freq= 2000000/Time;  //Calculation of frequency

}

freq = freq;  //To avoid the freq variable is compiler optimization.

}

}

sprintf(str, ''freq\n- %f\r\n'', freq);

/* Show to usart */

TM_USART_Puts(USART1, str);

}

}

}

hchaychi
Associate
Posted on May 08, 2015 at 12:37

Hi clive1

is it possible i use ch4 for external clock input ? and if yes how ?

Regards

Posted on May 08, 2015 at 19:20

No, you need to refer to the Timer Block Diagram in the Reference Manual

You can use an TIMx_ETR pins, internal sources (ITRx from other timers), TI1FP1 (CH1 side), TI2FP2 (CH2 side), TI1F_ED

You could perhaps use an EXTI interrupt for low bandwidth applications

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
hchaychi
Associate
Posted on May 11, 2015 at 08:43

Hi Clive1

Thank you very much

patrob680
Associate II
Posted on October 15, 2015 at 04:13

Hi all,

I am a beginner in this arena. If I use TIM5 (32-bit) CH1(PA.0) of STML1 to count external pulses in 10ms period (10ms active count, 10ms interval, again 10ms active), How to configure interrupt routine? Please educate me in this regard.

I've followed the earlier posts and started like this:

#include ''stm32l1xx.h''

#include ''misc.h''

#include ''stm32l1xx.h''

#include ''stm32l1xx_gpio.h''

#include ''stm32l1xx_rcc.h''

#include ''stm32l1xx_tim.h''

# define sample 20  

int count[sample];

int i;

int main(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

TIM_ICInitTypeDef   TIM_ICInitStructure;

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

/* TIM5 clock enable */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);

/* GPIOA clock enable */

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

   /*  TIM5 channel 1 pin (PA.0) configuration */

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

   GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;

   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;

   GPIO_Init(GPIOA, &GPIO_InitStructure);

   GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM5);

   /* TIM5 configuration: Input Capture mode  */

   TIM_TimeBaseStructure.TIM_Period = 0xF9FF;

// To generate interrupt in .01s (Count 64000-1)

   TIM_TimeBaseStructure.TIM_Prescaler = 4;      // 32MHz/(4+1) = 6.4MHz

   TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;

   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

   TIM_TimeBaseInit(TIM5, & TIM_TimeBaseStructure);

   TIM_ICInitStructure.TIM_Channel     = TIM_Channel_1;

   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 TIM5 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);

 /* Enable the CC1 Interrupt Request */

   TIM_ITConfig(TIM5, TIM_IT_CC1, ENABLE);

   while (1)

   {    

   // How to read total ticks in 10ms window and put sleep for another 10ms ?

  

  count[i] = TIM5->CNT;

  i++;

   }

}

Posted on October 15, 2015 at 07:00

Honestly this seems off-topic, can we not do that.

The TIM5_IRQHandler() would have to read consecutive captures of CNT stored in TIM5->CCR1, and do a delta computation between the two, of ticks at the timebase frequency. Using a 0-63999 count is going to make the math unduly complicated. If you just go with the maximal mode (Period = 0xFFFFFFFF), deltaticks = b - a; Where deltaticks, a, b are all uint32_t

In some situations PWM Input mode might be more helpful for period/duty, a single interrupt, and the timebase is automatically reset.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
patrob680
Associate II
Posted on October 26, 2015 at 04:36

Sorry, I misunderstood my requirements. I need to count pulses for consecutive 10ms period. Can I use RTC auto-wakeup interrupt to store TIM5-> CNT value after 10ms, reset CNT and re-count after 10ms? In that case, do I still need to configure TIM5 time-base interrupt?

Also, to store in a SD card text file (using FATFS), how to design a storage format for comma separated count values. I request some guidelines or

an example link, if available

.
patrob680
Associate II
Posted on October 26, 2015 at 13:43

Or to store in a .csv log file.