2022-07-08 07:40 AM
I try to recreate this tutorial:
I use STM32H747I-DISCO board instead. It's configured to generate 25kHz test signal. Main clock is set to 400MHz, the timers get 200MHz.
Here's a handle I use to hold my measurement state:
/**
* @typedef SWD_FrequencyCounter
* @struct
* @brief Frequency counter handle.
*/
typedef struct {
volatile uint32_t FT; ///< TIM frequency in Hz.
volatile uint32_t T1; ///< Ticks count 1.
volatile uint32_t T2; ///< Ticks count 2.
volatile uint32_t TC; ///< Ticks count.
volatile uint32_t PC; ///< Period counter.
volatile uint32_t F; ///< Measured frequency in Hz.
volatile uint8_t state;///< Measurement state (0 / 1).
} SWD_FrequencyCounter;
Here are my callbacks and initialization:
/**
* @fn void RPM_Init(TIM_HandleTypeDef*, uint32_t, uint32_t)
* @brief Initializes the timer configured as capture input for drive motor RPM measurement.
* @param htim TIM handle pointer.
* @param channel Input capture channel.
* @param frequency Timer input frequency in MHz.
*/
static HAL_StatusTypeDef RPM_Init(TIM_HandleTypeDef* htim, uint32_t channel, uint32_t frequency)
{
HAL_StatusTypeDef status;
frequencyCounter.FT = frequency * 1000000;
status = HAL_TIM_RegisterCallback(htim, HAL_TIM_IC_CAPTURE_CB_ID, RPM_ICCapture);
if (status != HAL_OK) return status;
status = HAL_TIM_RegisterCallback(htim, HAL_TIM_PERIOD_ELAPSED_CB_ID, RPM_PeriodElapsed);
if (status != HAL_OK) return status;
status = HAL_TIM_Base_Start_IT(htim);
if (status != HAL_OK) return status;
return HAL_TIM_IC_Start_IT(htim, channel);
}
/**
* @fn void RPM_ICCapture(TIM_HandleTypeDef*)
* @brief Calculates the frequency on the capture input.
* @param htim TIM handle pointer.
*/
static void RPM_ICCapture(TIM_HandleTypeDef* htim)
{
if (!frequencyCounter.state)
{
frequencyCounter.T1 = htim->Instance->CCR1;
frequencyCounter.PC = 0;
frequencyCounter.state = 1;
}
else
{
frequencyCounter.T2 = htim->Instance->CCR1;
frequencyCounter.TC =
frequencyCounter.T2 + frequencyCounter.PC * htim->Instance->ARR - frequencyCounter.T1;
if (frequencyCounter.TC != 0)
frequencyCounter.F = (uint32_t)(frequencyCounter.FT / frequencyCounter.TC);
else frequencyCounter.F = 0;
frequencyCounter.state = 0;
}
}
/**
* @fn void RPM_PeriodElapsed(TIM_HandleTypeDef*)
* @brief Counts the number of periods elapsed for the capture timer.
* @param htim TIM handle pointer.
*/
static void RPM_PeriodElapsed(TIM_HandleTypeDef* htim)
{
frequencyCounter.PC++;
}
It's almost exact copy of what's in the tutorial.
The timer used is TIM8, here's the configuration:
Interrupts enabled:
I have my test signal connected to the channel 2 input, and to my oscilloscope input, so I'm sure the test signal is present and valid.
I set the debugger breakpoint to the input compare callback function.
When no signal is present - it is not called what is expected.
Then I connect the test signal, the input compare callback is called.
But what I read is zero, no matter what input signal I provide. I tried various frequencies, from 32Hz to 100kHz.
CCR1 register value is always 0, and period counter (PC) is 1.
That doesn't make sense. It doesn't work. I'd expect at least PC to be 8.
The CCR1 register should contain any value but zero.
What am I doing wrong here? Where's the catch?
2022-07-08 08:03 AM
Oh, please delete it, or let it leave for other unlucky silly people like me...
CCR1 is for CHANNEL 1. I use CHANNEL 2. It works.