cancel
Showing results for 
Search instead for 
Did you mean: 

TIM5 External Clock Counter Issue

Hannah Rodgers
Associate II
Posted on July 17, 2017 at 23:15

I am using the STM32F4 board's TIM8 in order to generate a quadrature PWM signal at varying frequencies. That is working great; however, I need to decode the signal as it is being produced, aka, count the rising edges of channels A and B. I've tried using TIM8 to count it and I got huge numbers. When I tried to use TIM5 as shown below, the TIM_GetCounter(TIMx) function returns zero.  Any suggestions? Thank you in advance!

void InitializeTIM()

{

//sets clock for TIM8

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);

//sets clock for TIM5

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //MAY NEED TO CHANGE CLOCK

// PERIOD -> DEPENDS ON VELOCITY

float velocity = 0.25; //0.1; //meters/s

uint16_t half_period = Calculate_Period(velocity);

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure8; //creates structure for TIM8

TIM_OCInitTypeDef TIM_OCInitStructure; //creates structure for PWM

//Time base configuration TIM8

TIM_TimeBaseStructure8.TIM_Prescaler = PSC_Value;

TIM_TimeBaseStructure8.TIM_Period = half_period;

TIM_TimeBaseStructure8.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseStructure8.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure8);

//Enable TIM8 Preload register on ARR

TIM_ARRPreloadConfig(TIM8, ENABLE);

//TIM8 PWM1 Configuration --> 50% duty cycle

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

//CHANNEL A -> PC8

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

TIM_OCInitStructure.TIM_Pulse = half_period; // PHASE SHIFT

TIM_OC3Init(TIM8, &TIM_OCInitStructure);

//CHANNEL B -> PC9

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;

TIM_OCInitStructure.TIM_Pulse = (half_period/2); // PHASE SHIFT

TIM_OC4Init(TIM8, &TIM_OCInitStructure);

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure5; //creates structure for TIM5

//Time base configuration TIM5

TIM_TimeBaseStructure5.TIM_Prescaler = PSC_Value*0.3071;

TIM_TimeBaseStructure5.TIM_Period = 65535;

TIM_TimeBaseStructure5.TIM_ClockDivision = 0;

TIM_TimeBaseStructure5.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure5);

//Encoder count configuration TIM5

TIM_ETRClockMode1Config(TIM5, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00); //timer used, no prescaler, active on rising edge, no filter

// Enables counter

TIM_Cmd(TIM8, ENABLE);

TIM_Cmd(TIM5, ENABLE);

}

void InitializePINS()

{

//******************** TIM 8 ********************//

//GENERATING PWM

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

//creates structure for GPIOC

GPIO_InitTypeDef GPIO_InitStructure;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;//PC8 & PC9

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //alternative function

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //operating output

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //push or pull of pin

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // speed of pins -> slower saves power and cancels out some of the noise

GPIO_Init(GPIOC, &GPIO_InitStructure); //intializes structure

// Sets pin's alternative function to that of TIM8

GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_TIM8);

GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_TIM8);

//******************** TIM 5 ********************//

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

//creates structure for GPIOE

GPIO_InitTypeDef GPIO_InitStructure2;

GPIO_InitStructure2.GPIO_Pin = GPIO_Pin_2; //| GPIO_Pin_3;

GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_AF; //alternative function

GPIO_InitStructure2.GPIO_PuPd = GPIO_PuPd_UP; //push or pull of pin

GPIO_Init(GPIOA, &GPIO_InitStructure2); //intializes structure

// Sets pin's alternative function to that of TIM5

GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_TIM5);

//GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_TIM5);

//******************** TIM 5 ********************/

}

int main(void)

{

//Initializing functions

InitializePINS();

InitializeTIM();

pulse_counter = 0;

previous_round = 0;

while(1)

{

TIM_CtrlPWMOutputs(TIM8, ENABLE);

pulse_counter = TIM_GetCounter(TIM5);

totalPulses = cycle_counter - previous_round;

previous_round = cycle_counter;

}

return 0;

}

#timers #external-clock #pwm
5 REPLIES 5
Posted on July 18, 2017 at 00:14

From an external pin this is a TIM9_CH1 configuration, modify to suit..

void TIM9_Configuration(void)

{

  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

  /* Time base configuration */

  TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // 16-bit maximal

  TIM_TimeBaseStructure.TIM_Prescaler = 0;

  TIM_TimeBaseStructure.TIM_ClockDivision = 0;

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

  TIM_TimeBaseInit(TIM9, &TIM_TimeBaseStructure);

  TIM_TIxExternalClockConfig(TIM9, TIM_TIxExternalCLK1Source_TI1, TIM_ICPolarity_Rising, 0);

  TIM_Cmd(TIM9, ENABLE);

}
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on July 18, 2017 at 15:48

Thank you for replying! I tried the solution you gave me, but 0 was still returned from the GetCounter() function. I didn't change my pin config- I'm still using PA2, just switched it to TIM9. Do you think that  I need to config it an external pin for  a channel in TIM8 since that's the timer that is generating the PWM? Also, where did you find the information to know it's an external pin with the TIM9_CH1 config? I've looked over the datasheets and couldn't find it. Thank you in advance! 

Posted on July 18, 2017 at 17:48

I copied this from an external clock demo I built, doesn't use the same TIM and pins as you. I prefer to post code I know that works than dig through and correct code I didn't write on platforms I don't own.

The Data Manual provides specific pin associativity, the Reference Manual would cover possible internal connectivity options, you will need to review those in the context of your design/implementation.

The TIM9 code provides specifics on correct time base initialization, ie no prescaler, or other settings, just a wrapping 16-bit count, visible from TIM9->CNT to input clock stream on TIM9_CH1, in this case I think my source was PA2 (AF3)

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on July 18, 2017 at 17:53

PA2 is also TIM5_CH3 (AF2), I don't think that's routable using 

TIM_TIxExternalClockConfig(), you'd need to dig into those options.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Hannah Rodgers
Associate II
Posted on July 20, 2017 at 00:03

So, to anyone that is following this and would appreciate the solution I found.. 

Basically, after looking at the manual, I noticed a 'Figure 94'. It's related to the input triggers for the advanced timers 1 and 8. I reconfigured my PWM toggle to use TIM5 so that I could use TIM5's TRGO to input into TIM1  (ITR0); TIM1 will count the rising edges of TIM5 now. In other words, TIM5 is the master of TIM1. It seems to be working quite nicely- I get a triangle wave as I count up and store the values into an array. I hope this helps for anyone who needs it!