2019-10-11 02:55 AM
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;
}
2019-10-11 04:04 AM
> 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
2019-10-11 04:07 AM
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
2019-10-11 04:11 AM
Are you sure the signal does not ring?
2019-10-11 04:13 AM
Even if it did, I would still expect an update (maybe by more than 1) after 5 seconds, not after 10 seconds.
2019-10-11 04:20 AM
Post the content of TIM2 registers.
JW
2019-10-11 04:31 AM
Here is the register capture from Atollic Studio:
2019-10-11 04:36 AM
looks OK
2019-10-11 04:49 AM
What's your system/TIM clock?
Can you strip down the code to absolute minimum and retry?
jW
2019-10-11 04:54 AM
Did you confirm with an oscilloscope/LA that the input signal directly on the pin is 1:1?
JW