AnsweredAssumed Answered

STM32F4discovery measuring a pulse duration

Question asked by padbury.chris on Jan 22, 2013
Latest reply on Jan 24, 2013 by padbury.chris

I am having some trouble setting up an external pulse duration measurement on a Timer. Ideally I'd like to capture the duration of just the first incidence of a pulse on the desired pin, but that could require the use of interrupts and or debouncing.

Here's the code for setting up the Timer (TIM5):

/**
  *
  * Uses Timer PULSE_MEASUREMENT_TIM (with RCC as PULSE_MEASUREMENT_TIM_RCC)
  * on pin PULSE_MEASUREMENT_PIN of PULSE_MEASUREMENT_PORT (with RCC as PULSE_MEASUREMENT_PORT_RCC).
  * Also uses PULSE_MEASUREMENT_PINSOURCE and GPIO_AF_PULSE_MEASUREMENT_TIM.
  *
  */
uint32_t Pulse_Measurement_TIM_Config(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    TIM_ICInitTypeDef  TIM_ICInitStructure;
  
    /* PULSE_MEASUREMENT_TIM clock enable */
    RCC_APB1PeriphClockCmd(PULSE_MEASUREMENT_TIM_RCC, ENABLE);
  
    /* PULSE_MEASUREMENT_PORT clock enable */
    RCC_AHB1PeriphClockCmd(PULSE_MEASUREMENT_PORT_RCC, ENABLE);
    
    /* PULSE_MEASUREMENT_TIM channel2 configuration : PULSE_MEASUREMENT_PIN of PULSE_MEASUREMENT_PORT */
    GPIO_InitStructure.GPIO_Pin   = PULSE_MEASUREMENT_PIN;
    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_DOWN; //GPIO_PuPd_UP;
    GPIO_Init(PULSE_MEASUREMENT_PORT, &GPIO_InitStructure);
    
    /* Connect TIM pin to AF2 */
    GPIO_PinAFConfig(PULSE_MEASUREMENT_PORT, PULSE_MEASUREMENT_PINSOURCE, PULSE_MEASUREMENT_GPIO_AF_TIM);
  
    /* Enable the TIM4 global Interrupt //
    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    */
  
    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_PWMIConfig(PULSE_MEASUREMENT_TIM, &TIM_ICInitStructure);
  
    /* Select the TIM4 Input Trigger: TI2FP2 */
    TIM_SelectInputTrigger(PULSE_MEASUREMENT_TIM, TIM_TS_TI2FP2);
  
    /* Select the slave Mode: Reset Mode */
    //TIM_SelectSlaveMode(PULSE_MEASUREMENT_TIM, TIM_SlaveMode_Reset);
    TIM_SelectSlaveMode(PULSE_MEASUREMENT_TIM, TIM_SlaveMode_Gated);
    TIM_SelectMasterSlaveMode(PULSE_MEASUREMENT_TIM, TIM_MasterSlaveMode_Enable);
  
    /* TIM enable counter */
    TIM_Cmd(TIM4, ENABLE);
  
    return 0;
}

Here is the sub-routine for querying the timer:
/**
 *
 * This function queries the counter value of PULSE_MEASUREMENT_TIM. Also checks that the timer isn't still counting.
 *
 * returns
 *   positive integer : the number of us counted since last reset of the timer counter
 *   -1 : timer counter still counting (error)
 *
 */
uint32_t Query_Last_Pulse(void) {
    char return_message[23];
    unsigned int divisor = 84;
    unsigned int counter_value;
    unsigned int number_of_us;
      
    /* read counter value */
    counter_value = TIM_GetCounter(PULSE_MEASUREMENT_TIM);
    /* wait 8us */
    Delay_US(8);
    /* check if counter value has changed */
    if(counter_value == TIM_GetCounter(PULSE_MEASUREMENT_TIM)) {
        // it hasn't changed for return the number of microseconds;
        number_of_us = counter_value / divisor;     
    }
    else {
        sprintf(return_message, "%cERROR:_Still_Counting...%c", FRAMING_BYTE, FRAMING_BYTE);   // it hasn't stopped counting, error
        return -1;
    }
      
    return number_of_us; 
}

And finally here is the section of main code that defines the timer used etc and attempts to measure the duration of a pulse that happens between the two USER button presses:
#define   PULSE_MEASUREMENT_TIM           TIM5
#define   PULSE_MEASUREMENT_TIM_RCC       RCC_APB1Periph_TIM5
#define   PULSE_MEASUREMENT_PIN           GPIO_Pin_1
#define   PULSE_MEASUREMENT_PORT          GPIOA
#define   PULSE_MEASUREMENT_PORT_RCC      RCC_AHB1Periph_GPIOA
#define   PULSE_MEASUREMENT_PINSOURCE     GPIO_PinSource7
#define   PULSE_MEASUREMENT_GPIO_AF_TIM   GPIO_AF_TIM5
#define   PULSE_MEASUREMENT_OFFSET        0
  
#define   USER_BUTTON_PORT      GPIOA
#define   USER_BUTTON_PIN       GPIO_Pin_0
#define   USER_BUTTON_DEFAULT   0
  
//........
  
    /* Initialise PULSE_MEASUREMENT_TIM */
    Pulse_Measurement_TIM_Config();
      
    while(GPIO_ReadInputDataBit(USER_BUTTON_PORT, USER_BUTTON_PIN) == USER_BUTTON_DEFAULT);
      
    /* Reset PULSE_MEASUREMENT_TIM timer */
    TIM_SetCounter(PULSE_MEASUREMENT_TIM, PULSE_MEASUREMENT_OFFSET);
      
    Delay_ms(1000);
      
    while(GPIO_ReadInputDataBit(USER_BUTTON_PORT, USER_BUTTON_PIN) == USER_BUTTON_DEFAULT);
      
    sprintf(UART_Buffer, "Pulse(us)=%d\n", Query_Last_Pulse());
    Send_UART_Buffer();
  
//........

I always get "Pulse(us)=0", even when I define PULSE_MEASUREMENT_OFFSET as 10.

Outcomes