FRDM-K64  FTM measure pulse width

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

FRDM-K64  FTM measure pulse width

Jump to solution
2,403 Views
yuanhanchen
Contributor III

I am trying to measure the percentage of a PWM signal on a FRDM-K64 board. I am using the FTM2 FlexTimer in dual edge capture mode on channels 0-1. I'm getting the interrupts both for the rising and falling edge of the pulses.But after entering the interrupt function, simply enter a rising edge of a subroutine, but there is no falling entered a subroutine, why is there such a situation

 

code:

#include "board.h" #include "fsl_debug_console.h" #include "pin_mux.h" #include "clock_config.h" #include "fsl_ftm.h" /*******************************************************************************  * Definitions  ******************************************************************************/ /* The Flextimer instance/channel used for board */ #define DEMO_FTM_BASEADDR FTM2   /* FTM channel pair used for the dual-edge capture, channel pair 0 uses channels 0 and 1 */ #define BOARD_FTM_INPUT_CAPTURE_CHANNEL_PAIR kFTM_Chnl_0   /* Interrupt number and interrupt handler for the FTM instance used */ #define FTM_INTERRUPT_NUMBER FTM2_IRQn #define FTM_INPUT_CAPTURE_HANDLER FTM2_IRQHandler   /* Interrupt to enable and flag to read; depends on the FTM channel used for dual-edge capture */ #define FTM_CHANNEL0_INTERRUPT_ENABLE kFTM_Chnl0InterruptEnable   #define FTM_CHANNEL1_INTERRUPT_ENABLE kFTM_Chnl1InterruptEnable   #define FTM_CHANNEL0_FLAG kFTM_Chnl0Flag #define FTM_CHANNEL1_FLAG kFTM_Chnl1Flag   /* Get source clock for FTM driver */ #define FTM_SOURCE_CLOCK CLOCK_GetFreq(kCLOCK_BusClk)   /*******************************************************************************  * Prototypes  ******************************************************************************/   /*******************************************************************************  * Variables  ******************************************************************************/ volatile bool ftmIsrFlag = false; /*******************************************************************************  * Code  ******************************************************************************/ void FTM_INPUT_CAPTURE_HANDLER(void) {     if ((FTM_GetStatusFlags(DEMO_FTM_BASEADDR) & FTM_CHANNEL0_FLAG) == FTM_CHANNEL0_FLAG)     {     PRINTF("\r\n/**********************rasing interrupt****************************\n");         FTM_ClearStatusFlags(DEMO_FTM_BASEADDR, FTM_CHANNEL0_FLAG);     }     if ((FTM_GetStatusFlags(DEMO_FTM_BASEADDR) & FTM_CHANNEL1_FLAG) == FTM_CHANNEL1_FLAG)   {   PRINTF("\r\n/**********************falling interrupt****************************\n");   FTM_ClearStatusFlags(DEMO_FTM_BASEADDR, FTM_CHANNEL1_FLAG);   } }   /*!  * @brief Main function  */ int main(void) {     ftm_config_t ftmInfo;     ftm_dual_edge_capture_param_t edgeParam;     /* Board pin, clock, debug console init */     BOARD_InitPins();     BOARD_BootClockRUN();     BOARD_InitDebugConsole();       /* Print a note to terminal */     PRINTF("\r\nFTM dual-edge capture example\r\n");     PRINTF("\r\nSYSTEM Clock:%d\r\n",CLOCK_GetFreq(kCLOCK_CoreSysClk));     PRINTF("\r\nBUS Clock:%d\r\n",CLOCK_GetFreq(kCLOCK_BusClk));       FTM_GetDefaultConfig(&ftmInfo);     ftmInfo.prescale = kFTM_Prescale_Divide_128;     /* Initialize FTM module */     FTM_Init(DEMO_FTM_BASEADDR, &ftmInfo);       edgeParam.mode = kFTM_Continuous;     //Set capture edges to calculate the pulse width of input signal     edgeParam.currChanEdgeMode = kFTM_RisingEdge;     edgeParam.nextChanEdgeMode = kFTM_FallingEdge;       /* Setup dual-edge capture on a FTM channel pair */     FTM_SetupDualEdgeCapture(DEMO_FTM_BASEADDR, BOARD_FTM_INPUT_CAPTURE_CHANNEL_PAIR, &edgeParam, 0);       /* Set the timer to be in free-running mode */     DEMO_FTM_BASEADDR->MOD = 0xffff;     /* Enable channel interrupt when the second edge is detected */     FTM_EnableInterrupts(DEMO_FTM_BASEADDR, FTM_CHANNEL0_INTERRUPT_ENABLE);     FTM_EnableInterrupts(DEMO_FTM_BASEADDR, FTM_CHANNEL1_INTERRUPT_ENABLE);     /* Enable at the NVIC */     EnableIRQ(FTM_INTERRUPT_NUMBER);       FTM_StartTimer(DEMO_FTM_BASEADDR, kFTM_SystemClock);       while (1)     {     ;     } }

Original Attachment has been moved to: main.c.zip

Labels (1)
Tags (1)
1 Solution
1,278 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

Yes, that code doesn't take into account the case of FTMx_CNT overflow.

So if you want that code get the correct result, you need ensure FTMx_CNT doesn't overflow.(FTMx_CNT period > PWM period)

measure pulse width.jpg

You can increase the overflow period of FTMx_CNT by setup "ftmInfo.prescale".

If kFTM_Prescale_Divide_1, then pulseWidth = ((capture2Val - capture1Val) + 1) / (FTM_SOURCE_CLOCK / 1000000);

If kFTM_Prescale_Divide_128, then  pulseWidth = 128*((capture2Val - capture1Val) + 1) / (FTM_SOURCE_CLOCK / 1000000);

Best Regards,

Robin

View solution in original post

7 Replies
1,278 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

Hi yuanhan,

If you want measure pulse width, please refer the code in attached file.

Best Regards,

Robin

0 Kudos
1,278 Views
yuanhanchen
Contributor III

Hi Rbin_Shen,

Thank for your help,I've looked at your code, I also had a look at this example, the code for this but there is a problem, this code does not take into account the case of overflow interrupt, and overflow interrupt calculated according to the desired value in the first interval along the overflow interrupt flag is set to 0, so it is necessary in the first direction to generate an interrupt, but I list the code shows: generate interrupt flag is wrong, but why is wrong. Can you help me?

0 Kudos
1,279 Views
Robin_Shen
NXP TechSupport
NXP TechSupport

Yes, that code doesn't take into account the case of FTMx_CNT overflow.

So if you want that code get the correct result, you need ensure FTMx_CNT doesn't overflow.(FTMx_CNT period > PWM period)

measure pulse width.jpg

You can increase the overflow period of FTMx_CNT by setup "ftmInfo.prescale".

If kFTM_Prescale_Divide_1, then pulseWidth = ((capture2Val - capture1Val) + 1) / (FTM_SOURCE_CLOCK / 1000000);

If kFTM_Prescale_Divide_128, then  pulseWidth = 128*((capture2Val - capture1Val) + 1) / (FTM_SOURCE_CLOCK / 1000000);

Best Regards,

Robin

1,278 Views
yuanhanchen
Contributor III

Hi,Robin_Shen

Thank you for your answer, your answer was very helpful。

0 Kudos
1,278 Views
egoodii
Senior Contributor III

Yes -- as long as capture1Val and capture2Val are declared as 16-bit unsigned, and FTMxCNT is 0xFFFF (full 65536 counts)., and then you CAN IGNORE OVERFLOW.  For THEN a pulse (not clear if user is looking for 'high time', 'low time', or 'full pulse time') that happens to fall across an 'overflow time point' will get the proper mathematical result:  For example, 1 - 0xFFFF in 16 bit math is a proper 2, in 32bit it is 0xFFFF0002.

1,278 Views
yuanhanchen
Contributor III

Hi, EARL GOODRICH

Thank you for your answer, your answer was helpful。

0 Kudos
1,278 Views
egoodii
Senior Contributor III

IF that 'ftm_dual_edge_capture' demo code had defined capture1Val and capture2Val as uint16_t, (and only allowed the promotion to 32-bit math in the '+1' operation)  then the 'natural' 16-bit-integer math would preclude any requirement to worry about 'overflow' as long as the overall pulse width to measure is less than one full FTM cycle.