Input Capture maximum frequency measurement

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Input Capture maximum frequency measurement

1,368 Views
MohammedNassar
Contributor II

Hi,

Using QN9080C, I want to measure signals up to 1Mhz using Ctimer 1~3 Capture Inputs.

The APB bus clock is 16 Mhz, and the Datasheet says that the maximum frequency can be measured 1/2 APB bus clock so that I can measure Up to 8 Mhz, But the maximum frequency measured accurately is around 100 ~ 120 kHz.

I used Ctimers 1~3 with kCTIMER_TimerMode, kCTIMER_Capture_0/kCTIMER_Capture_1 and kCTIMER_Capture_FallEdge/kCTIMER_Capture_RiseEdge in Timer Configrations.

And the Code Sequence is CTIMER_Init, CTIMER_RegisterCallBack, CTIMER_SetupCapture and CTIMER_StartTimer.

0 Kudos
Reply
5 Replies

1,329 Views
MohammedNassar
Contributor II

Hello @EduardoZamora.

Thank you for your reply.

Yes, I used the simple_match_interrupt example. SDK 2.2.6

The callback function takes the CAP value two consecutive and calculates the Frequency.
And below there is my Code.

I tried to raise the APB clock to 32Mhz but got the same result. (CLOCK_SetClkDiv(kCLOCK_DivXtalClk, 0U); /* Set XTAL_DIV divider to value 1 */)

And below, there is all the clocks Configuration I am using.

No, I am not using any BLE or Low Power Feature.

The last results I could reach are 2MHz, but there is a significant error rate. 1MHz appears too much, which means there is an edge we could not catch.

void BOARD_BootClockRUN(void)
{
    /* Power up/Power down the module. */

    /* Set up clock selectors - Attach clocks to the peripheries */
    CLOCK_AttachClk(k32M_to_XTAL_CLK);                  /* Switch XTAL_CLK to 32M */
    CLOCK_AttachClk(kXTAL32K_to_32K_CLK);                  /* Switch 32K_CLK to XTAL32K */
    CLOCK_AttachClk(kXTAL_to_SYS_CLK);                  /* Switch SYS_CLK to XTAL */
    CLOCK_AttachClk(kAPB_to_WDT_CLK);                  /* Switch WDT_CLK to APB */

    /* Set up dividers */
    CLOCK_SetClkDiv(kCLOCK_DivOsc32mClk, 1U);                  /* Set OSC32M_DIV divider to value 2 */
    CLOCK_SetClkDiv(kCLOCK_DivXtalClk, 0U);                  /* Set XTAL_DIV divider to value 2 */
    CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 0U);                  /* Set AHB_DIV divider to value 1 */
    CLOCK_SetClkDiv(kCLOCK_DivFrg1, 0U);                  /* Set FRG_MULT1 to value 0, Set FRG_DIV1 to value 255 */
    CLOCK_SetClkDiv(kCLOCK_DivFrg0, 0U);                  /* Set FRG_MULT0 to value 0, Set FRG_DIV0 to value 255 */
    CLOCK_SetClkDiv(kCLOCK_DivApbClk, 0U);                  /* Set APB_DIV divider to value 1 */

    /* Enable/Disable clock out source and pins.*/

    /* Enable/Disable the specified peripheral clock.*/

}

Trying measure using Callback:

 

int volatile Is_First_Captured = 0;
uint32_t volatile IC_Val1 = 0;
uint32_t volatile IC_Val2 = 0;
uint32_t Difference = 0;

uint32_t CTIMER_GetCAPCounter(CTIMER_Type *base, uint32_t chl)
{
    uint32_t CR;
    CR = base->CR[chl];
    return CR;
}

void CaptureEdgeCb(uint32_t flags)
{
    if (Is_First_Captured==0) // if the first rising edge is not captured
    {
        IC_Val1 = CTIMER_GetCAPCounter(CTIMER2, kCTIMER_Capture_0); // read the first value
        Is_First_Captured = 1;  // set the first captured as true
    }
    else   // If the first rising edge is captured, now we will capture the second edge
    {
        IC_Val2 = CTIMER_GetCAPCounter(CTIMER2, kCTIMER_Capture_0);   // read second value

        Difference = IC_Val2 - IC_Val1;

        frequency = CLOCK_GetFreq(kCLOCK_CoreSysClk)/Difference;
        CTIMER_Reset(CTIMER2);  // reset the counter
        Is_First_Captured = 0; // set it back to false
        PRINTF("Freq  %lu\r\n",(unsigned long)frequency);

    }
}

/*!
 * @brief Main function
 */
int main(void)
{
    ctimer_config_t config;

    /* Init hardware*/
    BOARD_InitPins();
    BOARD_BootClockRUN();
    BOARD_InitDebugConsole();
    CTIMER_GetDefaultConfig(&config);
    config.input = kCTIMER_Capture_0;

    PRINTF("Inited \r\n");
    CTIMER_Init(CTIMER2, &config);
    CTIMER_RegisterCallBack(CTIMER2, s_CtimerCbArray, kCTIMER_SingleCallback);
    CTIMER_SetupCapture(CTIMER2, kCTIMER_Capture_0, kCTIMER_Capture_RiseEdge, true);
    CTIMER_StartTimer(CTIMER2);

    while (1)
    {
    }
}

Trying to measure with pooling:

/*!
 * @brief Main function
 */
int main(void)
{
    ctimer_config_t config;

    /* Init hardware*/
    BOARD_InitPins();
    BOARD_BootClockRUN();
    BOARD_InitDebugConsole();
    CTIMER_GetDefaultConfig(&config);
    //config.input = kCTIMER_Capture_1;

    PRINTF("Inited \r\n");
    CTIMER_Init(CTIMER2, &config);
    CTIMER_SetupCapture(CTIMER2, kCTIMER_Capture_1, kCTIMER_Capture_RiseEdge, false);

	uint32_t Capture1 = 0;
	uint32_t Capture2 = 0;
	uint32_t Period = 0;

    /* Clear the timer value */
    CTIMER_Reset(CTIMER2);

    /* Start the timer */
    CTIMER_StartTimer(CTIMER2);

    /* Enable the interrupts after starting the timer to void
        premature capture triggering
    */
    CTIMER_EnableInterrupts(CTIMER2,
                            (kCTIMER_Capture1InterruptEnable));
    while (1)
    {
        /**** FIRST FALLING EDGE ****/
		/* Wait for an interrupt to occur */
		while(!(CTIMER2->IR & CTIMER_IR_CR1INT_MASK)){}
	
	
		/* Fetch the capture value first, then clear the interrupts */
		Capture1 = CTIMER2->CR[kCTIMER_Capture_1];
		CTIMER2->IR = CTIMER_IR_CR1INT_MASK;
	
		/**** SECOND FALLING EDGE ****/
		/* Wait for an interrupt to occur */
	
		while(!(CTIMER2->IR & CTIMER_IR_CR1INT_MASK)){}
	
		/* Fetch the capture value first, then clear the interrupts */
		Capture2 = CTIMER2->CR[kCTIMER_Capture_1];
		CTIMER2->IR =  CTIMER_IR_CR1INT_MASK;
        Period = Capture2 - Capture1;
        PRINTF("%ld\r\n",32000000/Period);

    }
}

 

0 Kudos
Reply

1,313 Views
EduardoZamora
NXP TechSupport
NXP TechSupport

Hi,

Could you please help us with more details about the jumper configuration of your board?

Also, please consider removing or replacing the PRINTF() function as it may slow down the execution of your application.

Regards,
Eduardo.

0 Kudos
Reply

1,299 Views
MohammedNassar
Contributor II

Hi, @EduardoZamora.

My jumper configuration:

JP8, JP14 Connected

JP7 -> VDD SEL 3V

JP2 -> QN9080 Power Supply On Board 

And the printf after capturing the two consecutive edges, so there is no problem.

The error in the second edge capture, and there is not so much code between edges capturing.

Image20220911140606.jpg

Image20220911132631.jpg

0 Kudos
Reply

1,275 Views
EduardoZamora
NXP TechSupport
NXP TechSupport

Hello,

Could you please take a look at this article?

[LPC845] Pulse-width Measurement Using CTIMER

This article mainly introduces how to use CTIMER measuring pulse-width in LPC584, but same steps and considerations should apply to QN9080 CTIMER module and you could use it as a base.

Regards,
Eduardo.

0 Kudos
Reply

1,335 Views
EduardoZamora
NXP TechSupport
NXP TechSupport

Hello Mohammed,

I apologize for my late response.

Just to confirm, are you using any of the example projects from the SDK as base for your application? Could you please help us with more details about your callback?

Also, could you please confirm if you are using a specific APB clock input divider?

By any chance, are you using any of the BLE or low power features?

Regards,
Eduardo.

0 Kudos
Reply