AnsweredAssumed Answered

Timer(s) with 2 Ext inputs, one gating the other

Question asked by digital_dreamer on Dec 12, 2013
Latest reply on Dec 14, 2013 by digital_dreamer
I've been coding on the STM32F4 for the past couple years and love the MCU.

However, I'm having trouble figuring out how to bring in two external signals and use one as the gate for the other. I'm planning on bringing in a 10MHz frequency and have a counter count it via external reference 1Hz signal (RTC output).

Currently, I have no problem getting a counter going via external trigger. I have no problem with using a external signal as a gate, but I can't do both -- have a external clock counting only during the logic high/low of another external signal.

This should be simple, but I just can't see it. Each attempt causes the external clock to revert to internal. I tried using two counters in a master/slave setup. My last attempt, shown below, is using a 32-bit timer and the Input Capture registers, which appears to be what many of the examples use.

Preferably, I don't want to use a interrupt, to keep latencies down. But, if I must, I'll just add the latency in the calculation. I figure I may have to use an interrupt to clear the registers.

void SetupCounter(void)
{
    GPIO_InitTypeDef          GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
    TIM_OCInitTypeDef         TIM_OCInitStructure;
    TIM_ICInitTypeDef         TIM_ICInitStructure;
    NVIC_InitTypeDef          NVIC_InitStructure;
 
    /* Enable TIM2 clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
 
    /* Enable GPIOA clock */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
 
    /* Configure PA0 and PA1 pins as AF */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN ;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
 
    /* Connect TIM2 ETR to PA0 pin and TIM2 CH2 to PA1 */
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_TIM2);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM2);
 
    /* Input Trigger selection */
    TIM_ETRClockMode1Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);
 
    /* TIM2 time base configuration - fed by external calibrated timebase */
    TIM_TimeBaseStructure.TIM_Period = -1;
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
 
    /* TIM1 Input Capture Configuration */
    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 = 0;
    TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);
 
    TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);
 
    /* Select the slave Mode: Gated mode */
    TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Gated);
 
    /* Select the TIM2 Input Trigger: TIM_TS_ITR2 */
    TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);
 
    /* Enable the TIM2 global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
 
    /* Enable the CC2 Interrupt Request */
    TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
 
    /* Enable TIM2 counter */
    TIM_Cmd(TIM2, ENABLE);
}
 
void TIM2_IRQHandler(void)
{
    /* Clear TIM2 Capture compare interrupt pending bit */
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
 
    /* Get the Input Capture value */
    CCR2Value = TIM2->CCR2;
    TIM2->CCR2 = 0;
    TIM2->CNT = 0;
 
    CCR2Flag = SET;
}


Outcomes