Hi, I'm trying to measure the frequency of a square wave using the MCU on title. I have LPTMR running in free mode and I'm capturing its value every rising edge interrupt of the GPIO pin of the wave. I've configured the system clock to 40MHz and the BUS and LPTMR to 20MHz. I can correctly read frequencies until 300kHz, but after this value, the result is wrong. Does anyone have any idea why? The configurations using Processor Expert are on attachment.
Thanks in advance.
/* Variables both used inside ISR and out */
volatile uint32_t countArray[2];
volatile uint8_t countIndex;
/* Frequency variables */
volatile uint32_t realFrequency;
const uint32_t icFreq = 20000000;
void GPIO_ISR(void) {
/* Clear Port B Interrupt Flag */
PORTC->ISFR = PORT_ISFR_ISF_MASK;
if (countIndex != 2) {
/* Get current counter value */
LPTMR0->CNR = (0U & LPTMR_CNR_COUNTER_MASK); // Write a dummy value before reading
countArray[countIndex++] = LPTMR0->CNR;
}
}
int main(void) {
CLOCK_SYS_Init(g_clockManConfigsArr, CLOCK_MANAGER_CONFIG_CNT,
g_clockManCallbacksArr, CLOCK_MANAGER_CALLBACK_CNT);
CLOCK_SYS_UpdateConfiguration(0U, CLOCK_MANAGER_POLICY_AGREEMENT);
/* Initialize Pins */
PINS_DRV_Init(NUM_OF_CONFIGURED_PINS, g_pin_mux_InitConfigArr);
/* Install GPIO ISR */
INT_SYS_InstallHandler(PORT_IRQn, &GPIO_ISR, (isr_t *) 0);
INT_SYS_EnableIRQ(PORT_IRQn);
/* Initialize LPTMR */
LPTMR_DRV_Init(INST_LPTMR1, &lpTmr1_config0, true);
/* MAIN LOOP */
for (;;) {
if (countIndex == 2) {
/* Verify timer overflow */
if (countArray[1] < countArray[0]) {
realFrequency = icFreq / (countArray[1] + 65535 - countArray[0]);
} else {
realFrequency = icFreq / (countArray[1] - countArray[0]);
}
}
}
解決済! 解決策の投稿を見る。
Hi rjmalmeida0@gmail.com,
There is some overhead.
You can toggle a GPIO in the GPIO_ISR when the CNR is being read.
Then, if you compare the two signals, you should see a delay of a few micro seconds.
The period of 300kHz signal is just 3.33us.
So, you can’t measure a signal with a period that is shorter than what it takes to read the counter.
You can use Flex Timer (FTM) in Dual-Edge Capture Mode.
Please take a look at Section 45.5.26 Dual Edge Capture Mode, RM rev.11.
And the ftm_signal_measurement_s32k116 SDK example in S32 Design Studio.
Regards,
Daniel
Hi rjmalmeida0@gmail.com,
There is some overhead.
You can toggle a GPIO in the GPIO_ISR when the CNR is being read.
Then, if you compare the two signals, you should see a delay of a few micro seconds.
The period of 300kHz signal is just 3.33us.
So, you can’t measure a signal with a period that is shorter than what it takes to read the counter.
You can use Flex Timer (FTM) in Dual-Edge Capture Mode.
Please take a look at Section 45.5.26 Dual Edge Capture Mode, RM rev.11.
And the ftm_signal_measurement_s32k116 SDK example in S32 Design Studio.
Regards,
Daniel
Hi @Daniel Martynek,
Thank you for your response. I've figured out that there is a 15 cycles delay between the assertion of the input pin and the start of the ISR. Due to this delay, the ISR + Delay time is actually longer than the period of the wave to be read. This is why the final frequency value is wrong.
As for the Capture Mode, is there a documented maximum frequency that the FTM can read?
Regards,
Rui
Hi Rui,
The input signal is synchronized to the FTM input clock first.
The max FTM input clock frequency is given by SYS_CLK.
Then, the signal can be filtered (45.5.5.1 Filter for Input Capture Mode).
With the filter disabled, the delay is 3 rising edges of the FTM input clock.
Regards,
Daniel