cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L4 Timer: External clock count both edges

PKulh
Associate II

Hello,

I need to count the number of (positive and negative) edges in a signal within certain time period. For that I use a timer on STM32L452. The AN4776 says that External Clock Mode 1 is able to update the counter on both edges (for the price of not being able to trigger). I tried this (see the code below) and figured out that with a 50% duty cycle square test signal of 100mHz the CNT register is incremented every 10 seconds by 2. I would expect the CNT to increment by 1 every 5 seconds.

What am I doing wrong?

Thanks

Petr

Below is my code using TIM2 CH1 for clock and CH3 for capture (without clock, DMA and interrupt initialization):

// ---------- initialize GPIO ------------
    GPIO_InitTypeDef GpioInitStruct;
 
    // initialize the bitstream pin
    GpioInitStruct.Pin = GPIO_PIN_5;
    GpioInitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GpioInitStruct.Mode = GPIO_MODE_AF_PP;
    GpioInitStruct.Pull = GPIO_NOPULL;
    GpioInitStruct.Alternate = GPIO_AF1_TIM2;
    HAL_GPIO_Init(GPIOA, &GpioInitStruct);
 
    // initialize the sync pin
    GpioInitStruct.Pin = GPIO_PIN_2;
    GpioInitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GpioInitStruct.Mode = GPIO_MODE_AF_PP;
    GpioInitStruct.Pull = GPIO_NOPULL;
    GpioInitStruct.Alternate = GPIO_AF1_TIM2;
    HAL_GPIO_Init(GPIOA, &GpioInitStruct);
 
    // ------------ initialize timer -------------
    // basic initialization of the structure
    TIM_HandleTypeDef *pTmrHandle;
    pTmrHandle->Instance = TIM2;
    pTmrHandle->Init.Prescaler = 0;
    pTmrHandle->Init.CounterMode = TIM_COUNTERMODE_UP;
    pTmrHandle->Init.Period = 0xffff;
    pTmrHandle->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    pTmrHandle->Init.RepetitionCounter = 0;
    pTmrHandle->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
 
    // configure the clock source
    TIM_ClockConfigTypeDef ClockSourceConfig;
    ClockSourceConfig.ClockFilter = 0;                           // no filter
    ClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;  // no prescaler
    ClockSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_BOTHEDGE;   // trigger on both edges
    ClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_TI1ED;          // both edges
 
    // select the clock using the above clock configuration
    if (HAL_TIM_ConfigClockSource(pTmrHandle, &ClockSourceConfig) != HAL_OK) {
        return false;
    }
 
    // initialize input capture time base
    if (HAL_TIM_IC_Init(pTmrHandle) != HAL_OK) {
        return false;
    }
 
    // configure the input-capture channel (triggered by the sync signal) to trigger on both edges
    TIM_IC_InitTypeDef InputCaptureConfig = {
            .ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING,          // trigger on the rising edge
            .ICSelection = TIM_ICSELECTION_DIRECTTI,                // direct mapping of timer inputs
            .ICPrescaler = TIM_ICPSC_DIV1,                          // no divider - we want to count all edges
            .ICFilter = 0,                                          // no filter
    };
    // trigger on the rising edge of CH3 (sync)
    if (HAL_TIM_IC_ConfigChannel(pTmrHandle, &InputCaptureConfig, TIM_CHANNEL_3) != HAL_OK) {
        return false;
    }
 
    // configure both edges on CH1 (clock)
    InputCaptureConfig.ICPolarity = TIM_INPUTCHANNELPOLARITY_BOTHEDGE;
    if (HAL_TIM_IC_ConfigChannel(pTmrHandle, &InputCaptureConfig, TIM_CHANNEL_1) != HAL_OK) {
        return false;
    }
 
 
// to start reception:
    if (HAL_TIM_IC_Start_DMA(pTmrHandle, TIM_CHANNEL_3,  (uint32_t*)dmaBuffer_, 2 * dmaBlockSize_) != HAL_OK) {
        return false;
    }

20 REPLIES 20

> CNT register is incremented every 10 seconds by 2. I would expect the CNT to increment by 1 every 5 seconds.

How exactly do you observe CNT?

JW

I tried different ways: either by capturing via DMA, or by frequently stepping an idle loop in the program via debugger (the counter keeps running). This case was when stepping with a debugger.

Petr

Uwe Bonnes
Principal III

Are you sure the signal does not ring?

Even if it did, I would still expect an update (maybe by more than 1) after 5 seconds, not after 10 seconds.

Post the content of TIM2 registers.

JW

Here is the register capture from Atollic Studio:

0690X00000ApW84QAF.png

looks OK

What's your system/TIM clock?

Can you strip down the code to absolute minimum and retry?

jW

Did you confirm with an oscilloscope/LA that the input signal directly on the pin is 1:1?

JW