AnsweredAssumed Answered

stm32 timer IC counter reset

Question asked by g.a on Feb 25, 2014
UPDATE: The TIM_SelectInputTrigger function and the TIM_ITRxExternalClockConfig function both write to the TS bits in the TIMx_SMCR register so the final value is ITR2 overwriting the TI1FP1 value set.  Because I am using an external clock mode the trigger input is being used to increment the counter so can hardly be used to reset it too.  From Figure 160 in RM0136 the only MUXes that look at the ITR lines is the TRGI so external clock 2 etc. can't be used there really is only one TRGI signal so it seems like it is completely impossible to chain timers to prescale and simultaneously reset the counter in hardware (without going off chip).

I'm trying to time the space between button presses of the user button on the stm32f3discovery board.  I'm using TIM3 to divide the clock down and TIM2 on the IC1 channel, I've got as far as capturing the current state of the counter on a button press however I'd like to have this trigger an update event to reset the counter.

The preamble and TIM3 setup is as follows:
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // Enable TIM3 logic

// Timer values
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_PrescalerConfig(TIM3, 0x01, TIM_PSCReloadMode_Immediate);
TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);
TIM_Cmd(TIM3, ENABLE); // Start timer 3

So TIM3 is now free running and sends periodic output trigger events.  To this point everything is looking dandy.
Next the PA0 pin which has the button connected is configured to mode AF1 which sends it to channel 1 on timer 2, this is shown below and appears to work fine too.

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);     // GPIOA clk en
GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;                         // PA0 - AF1
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_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_1);

Next I try setting up the counter with rather redundant setting of defaults:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_PrescalerConfig(TIM2, 0x01, TIM_PSCReloadMode_Immediate);

The IC1 channel is set up:

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

So perhaps the missing reset has something to do with the sections above?  Next I set the interrupts which seems to work fine.

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

Now we get the where the problem seems likely to lie, I expect the following lines to take the output of the filter that feeds channel 1 and use it as the reset trigger for the slave mode counter.  In my mind these two lines are instructing the counter to do what I want and yet it never resets itself.

TIM_SelectInputTrigger(TIM2, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);

Then we set ourselves to slave mode and take the ITR2 signal as a clock which is the output of TIM3 as per table 62 in the data sheet.  This bit is working fine.

TIM_ITRxExternalClockConfig(TIM2, TIM_TS_ITR2);

So on every button push we get into the interrupt handler which provides a new ever increasing value in channel 1 (TIM_GetCapture1(TIM2)), the TIM3 clock prescaler seems to be working fine but it just seems like the counter isn't getting reset.  Of course one can take the differences between results but then when the counter rolls that's a whole bunch of extra stuff to put in and the data sheet pretty much says straight up that the counter can be made to reset on a capture event so I'd rather have this happen.  I know most of the code I added isn't important but not knowing where the problem is the more the merrier!

Does anyone have any thoughts on what I've done wrong?

Many thanks