How to validate the pulse duration with the generated timer count?

177 views Asked by At

I am working on a small project which utilizes STM32F411RE. I am applying input pulses at a frequency of 100 Hz and am also measuring the applied pulses using a scope. My aim is to initiate a General Purpose Timer counter upon the detection/rising edge of the input pulse and stop the timer's counter upon the falling edge of the same pulse. I have everything configured and programmed accordingly. I am adding my code for everyone's reference:

Before that, This is my configuration in CubeMx: Clock Configuration = 80 MHz Internal Clock Division = 1 ( APB1 = APB2 = 80 MHz) TIM 2 enabled and sourced with the Internal clock.

I implemented this code and tried looking for formulas but everywhere they mention different formulas which leaves me in a confused state.

volatile uint32_t timerCountValue = 0;
uint32_t currentValue = 0;
uint32_t timeDifference = 0;
uint32_t counterMaxValue = 4294967295; //Timer's Counter max value

void HAL_GPIO_EXTI_Callback( uint16_t GPIO_Pin )
{
    if( GPIO_Pin == GATE1_Pin )
    {
        if( HAL_GPIO_ReadPin( GATE1_GPIO_Port, GATE1_Pin ) == GPIO_PIN_SET )
        {
            HAL_TIM_Base_Start( &htim2 );
            timerCountValue = TIM2->CNT;
            while( HAL_GPIO_ReadPin( GATE1_GPIO_Port, GATE1_Pin ) == GPIO_PIN_SET )
            {
                if( HAL_GPIO_ReadPin( GATE1_GPIO_Port, GATE1_Pin ) == GPIO_PIN_RESET )
                {
                    HAL_TIM_Base_Stop( &htim2 );
                    currentValue = TIM2->CNT;
                    break;
                }
            }
        }
        //Calculate the time difference
        if( currentValue >= timerCountValue )
        {
            timeDifference = currentValue - timerCountValue;
        }
        else
        {
            timeDifference = counterMaxValue - timerCountValue + currentValue + 1;
        }
    }
}

Now, based on the attached code, I do get some value inside the 'timeDifference' variable. But how do I validate if the value stored inside the 'timeDifference' variable matches with the pulse width value which I see on the scope.

From the Scope : Pulse width (fall time - rise time) = 4.16ms From the code : Timer counter value (timeDifference variable) holds 15764 then in the second instance holds 61454 and the value keeps on fluctuating.

Can someone please help me understand the conversion and validation part of this project? Also, how to calculate a good prescaler value? Currently I have set my Prescaler value to 39999 but not sure how to properly calculate it. Please advise.

1

There are 1 answers

2
Clifford On

As the counter is a 32-bit, your timeDifference is unnecessarily over-complicated.

//Calculate the time difference
uint32_t timeDifference = currentValue - timerCountValue;

will work due to modulo-2 arithmetic. See How to deal with a wrapping counter in embedded C

HAL_GPIO_EXTI_Callback() is an interrupt handler, but your code has a busy-wait loop unsuited to interrupt handling. Your handler should run to completion quickly and deterministically with no delays or busy-wait loops. The handler in this case should operate as a state-machine, using a static flag or state variable to indicate whether it is waiting for the start or end of the pulse.

Your method of pulse capture is in any event sub-optimal. The timer hardware has input-capture capability where the timer/counter can be gated directly by a GPIO input, allowing the pulse to be measured directly (and accurately) with no software overhead. See https://controllerstech.com/input-capture-in-stm32/ for an example of pulse measurement using input-capture.