AnsweredAssumed Answered

How to properly initialize TPM1_CH0 for Pulse-Width Measurement of Ultrasonic Range Finder

Question asked by exgreyfox on Oct 5, 2015
Latest reply on Oct 11, 2015 by Erich Styger

I have written some baremetal code to interface a a Ping Parallax ultrasonic range finder using interrupts but I am having some trouble properly initializing the KL25Z TPM1 for input capture. Basically I just need to measure the time between the rising edge and falling edge of the sensor output. I am using TPM1_CH0 on pin PTA12 for sensor output to the KL25Z freedomboard. I have taken the approach that Alice_Yang suggested in this thread: Re: Using of TPM to calculate pulse width in KL25Z Here is how I have initialized the hardware. Please correct me if I'm wrong.

 

TPM1_CH0 Initialization:

 

void TPM1_CH0_Timer_Capture_Init(void)
{
  SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK;                /* Enable clock to PORTA */
  PORTA_PCR12 = PORT_PCR_MUX(3);                    /* Set Port A for TPM1CH0 input */

  SIM_SCGC6 |= SIM_SCGC6_TPM1_MASK;                 /* Enable clock to TPM1 */

  SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL_MASK;            /* We Want MCGPLLCLK/2 */
  SIM_SOPT2 &= ~(SIM_SOPT2_TPMSRC_MASK);
  SIM_SOPT2 |= SIM_SOPT2_TPMSRC(1);                 /* We want the MCGPLLCLK/2 */ 
    
  TPM1_SC |= 0x00;                                  /* Blow away the control registers to ensure that the counter is not running */
  TPM1_CONF |= 0x00;                                /* Blow away the control registers to ensure that the counter is not running */

  TPM1_SC = TPM_SC_PS(TPM1_CLK_PRESCALE);           /* Setup prescaler to DIV by 4 */
  TPM1_MOD = 0xFFFF;                                /* Set max modulo */

   /* Input Capture mode rising edge interrupt first, ELSB:ELSA = 01, MSB:MSA = 00 */
   TPM1_C0SC |= TPM_CnSC_CHIE_MASK | TPM_CnSC_ELSA_MASK & ~(TPM_CnSC_ELSB_MASK) & ~(TPM_CnSC_MSA_MASK) & ~(TPM_CnSC_MSB_MASK); 
}

 

Here is the logic I plan to follow inside the FTM1_IRQHandler() I still have not implemented the handler

 

void FTM1_IRQHandler(void)
{
  //clear channel interrupt flag
  //stop timer
  //check for rising or falling edge interrupt
       //if rising edge interrupt
            //save TPM counter value in var called rising_val
            //set falling edge interrupt
            //start the timer
       //if falling edge interrupt
            //save TPM counter value in var called falling_val
}

 

And the sequence of events in main:

 

int main(void)
{
  /* Core Clock is now at 48MHz using the 8MHZ Crystal */
  pll_init(8000000, LOW_POWER, CRYSTAL, 4, 24, MCGOUT); //Using Eli Highs' PLL init mcg library files

  TPM1_CH0_Timer_Capture_Init();
  Init_PORTA();

  for(;;) {
// logic here gives the range finder the start pulse it needs
       GPIOA_PDDR |=  GPIO_PTA1_LOC;           /* make PortA_1 an output */
       GPIO_PTA2_HIGH;                         /* PTA2 HIGH for A to B Level Shifter DIR */

       GPIO_PTA1_HIGH;
       DelayUs_NoIRQ(5);                       /* delay 5us */
       GPIO_PTA1_LOW;

       DelayUs_NoIRQ(300);                     /* delay 300us */

       GPIOA_PDDR &= ~GPIO_PTA1_LOC;           /* make PortA_1 an input */
       GPIO_PTA2_LOW;                          /* PTA2 LOW for B to A Level Shifter DIR */
// Logic here handles the IRQ and pulse width measurement
       enable_irq (INT_TPM1-16);               /* Enable Timer1 interrupt in NVIC */
       TPM1_SC |= TPM_SC_CMOD(1);              /* Enable the TPM1_CH0 Timer */

       DelayMs_NoIRQ(19);                      /* delay 19ms */

       disable_irq (INT_TPM1-16);              /* Disable Timer1 interrupt in NVIC */

       val = falling_edge_val - rising_edge_val;   /* Save captured pulse width value */ 
  }
  return 0;
}

 

Is there anything wrong with how I've initialized my TPM1_CH0 capture input for TPM1? Thank you for any assitance.

Outcomes