This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/MSP430FR5969: How to write the ISR for TimerA1 module?

Part Number: MSP430FR5969
Other Parts Discussed in Thread: CSD

Tool/software: Code Composer Studio

Hello everyone,

I'm trying to use the grove ultrasonic ranger for some distance measurement.

The plan is to send out a pulse of 10us and capture the high-time of the echo from the sensor and then calculate the distance.

However it seems that i can't get into the ISR (which i copied from one of the example code file of TA1). Im already using TA0 for some other job and therefore have to use TA1:

I configured TA1 in capture mode and on P1.2 (which is the Timer 1 CCR1 register according to the datasheet) I'm waiting to recieve to echo signal and trigger the ISR:

#include <msp430.h>
#include "stdint.h"
#include <string.h>
#include <stdlib.h>


unsigned int counter;
unsigned int distance_cm;

// Timer A1 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMER1_A0_VECTOR
__interrupt void Timer1_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER1_A0_VECTOR))) Timer1_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
    if (TA1CCTL1 & CCI)            // Rising edge
        {
            counter = TA1CCR1;      // Copy counter value to variable
        }
        else                        // Falling edge
        {
            // Formula: Distance in cm = (Time in uSec)/58
            distance_cm = (TA1CCR1 - counter)/58;
        }
        TA1CCTL1 &= ~CCIFG;           // Clear interrupt flag - handled
}

// Clock System Setup
void clock_init(){

      CSCTL0_H = CSKEY >> 8;                    // Unlock CS registers
      CSCTL1 = DCOFSEL_0;                       // Set DCO to 1MHz
      CSCTL2 = SELA__VLOCLK | SELS__DCOCLK | SELM__DCOCLK;  // Set SMCLK = MCLK = DCO
                                                // ACLK = VLOCLK
      CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;     // Set all dividers to 1
      CSCTL0_H = 0;                             // Lock CS registers
    }

//timer1A setup
void timer_init(){

    TA1CTL = TASSEL_2 | MC_2 ;          // SMCLK, cont. mode
    TA1CCTL1 = CM_3 | SCS | CAP | CCIE; //capture on rising&falling edge, synchronize CCI1A with clock,
                                        // capture mode, capture interrupt enable
    }

void peripherals_init(){

    P1DIR |= BIT3;                   //set output for trigger
    P1DIR &= ~BIT2;                  //set input for echo
    P1SEL0 |= BIT2;                  //configure P1.2 as capture input (CCI1A) for TimerA1
    P1SEL1 &= ~BIT2;

   }

void main (void){
   WDTCTL = WDTPW | WDTHOLD;      //Stop Watchdog Timer
   PM5CTL0 &= ~LOCKLPM5;          // This is Needed for MSP430FR5969!

   clock_init();
   timer_init();
   peripherals_init();
   init_UART();

   P1OUT &= ~BIT3;                  //keep trigger low

// Welcome String over UART
   send_str("Ultrasonic Distance Measurement in cm: ");

   __bis_SR_register(GIE);


   while (1)
       {
           // measuring the distance
           P1OUT ^= BIT3;                      // trigger high
           __delay_cycles(10);                  // 10us wide
           P1OUT ^= BIT3;                       // trigger low
           __delay_cycles(500000);              // 0.5sec measurement cycle

       }
}

  • Hi Marc
    Can you make the10 us to be longer to see if there will be a timer capture interrupt?
  • > #pragma vector = TIMER1_A0_VECTOR
    This is for TA1CCR0 (only). Try:
    > #pragma vector = TIMER1_A1_VECTOR

    That said, you'll find it very difficult to capture both edges of a 10us pulse running at 1MHz. (Estimate a minimum of 20-30 MCLKs just to get into/out of the ISR, and you only have 10 MCLKs.) Options:

    1) Speed up MCLK. At 8MHz you'll have 80 MCLKs, which may be feasible. (Hint: Grab TA1CCR1 as the first thing.) 16MHz would be fairly comfortable.
    2) Use DMA to grab the CCR value(s). Unfortunately, I don't see TA1CCR1 among the available DMA triggers [SLAS704F Table 6-12]. Could you use TA1CCR2 (P1.3) instead? Also I don't know of a good way to capture the corresponding TA1CCTL1 so you'll have to piece the sequence together later.

  • 3) Split the input wire and feed it into both TA1.1 and TA1.2. Use CCR1 for one edge and CCR2 for the other. They have a common timebase, so the two captures are comparable.

    Yeah, speeding up the clock is probably the simplest.

    [Edit: Fixed clumsy wording.]

  • Hello Marc,

    one remark,
    it is a good practice to avoid statements like this:
    distance_cm = (TA1CCR1 - counter)/58;
    within interrupt functions.
    A divide operation takes a lot of time and if possible should be done outside of an interrupt.
    Just an example:
    an integer division on an 8MHz F1611 took about 57µs.
    On 5994 @ 16MHz it might take more than 20µs, probably.

    I hope, tomorrow or on Sunday I will have time to look into your code.

  • Bruce,

    there is a divide operation within an ISR.
    A divide operation @ 1MHz would take 100, maybe 200 or even 500+ µs.
  • Hello Mark,

    I did additional investigation regarding an Integer-Integer division.

    In case of CPUX architecture, which is supported by MSP430FR5969,
    an Integer-Integer divide by a fixed value equal to 41 (2^5+2^3+2^0)
    takes close to 200 CPU cycles.
    However, using Horner or Horner+CSD schema, a divide operation execution time
    can be reduced by a factor close to 10.

    Please, look a table below which was extracted from www.ti.com/.../slaa329.pdf

    In your case, when using Horner schema, a divide by a value of 58, which is represented by polynomial 2^5+2^4+2^3+2^1 probably will take,
    lets guess, 30% more cycles because of one position longer polynomial.

    Still, worth to know that Horner method exist.

  • > there is a divide operation within an ISR

    The divide happens on the falling edge, but the race happens on the rising edge. Based on "0.5sec measurement cycle", there's quite a lot of time to do the divide, whether it's done in the ISR or in main.
  • Bruce,
    I agree with you.

    I decided to post my remark to the original code when I realized
    how huge trap that divide could be when mixed with other interrupts.
  • Hello togehter

    first of all thank you very much for your help. Im actually quite new into this whole microcontroller area.

    After some research i also figured out that the Timer0_a1 vector is only the vector for the ccr0 register and that i have to use the Timer1_a1 vector.

    I will definitely take a look at the horner scheme, but I also thougt a little bit for myself.

    Wouldnt it be possible to just capture the actual values of the timer register right at the moment of the rising and falling edge with the ISR and do the distance calculation in the main function.

    The distance i want to measure is only the water level in a tank which will only be chaning slowely and wont even change at all for most of the time, i thought about only trigger a measurement before a pump will be activated. Maybe it will be also possible tu take just one timer period, bc this would be enough to determine the water level.

    Also I could run the whole system @ 16Mhz to get some more time, what someone mentioned already.

    The thing is i don't know how long in time the echo impulse which the sensor will sent back to the 10us trigger impulse will be but i actually think it will be longer than 10us.

    Kind Regards

    Marc

  • Hello Marc,

    I decided to reply to your post after I have seen a divide operation in an ISR.

    Bruce has explained that in your particular case a divide processing time is not an issue.

    Do not worry about polynomial division according to Horner scheme.
    As I remember it consist off on two loops and two assignments.
    It is not a rocket to science to implement it.

    You say: The distance i want to measure is only the water level in a tank ...

    Do you know that excellent document: www.ti.com/.../snaa270.pdf ?

    I have no experience in an ultrasonic measurements.
    Without a solid understanding of an air, water ultrasonic propagation and the bottom reflection physical effects,
    the measurement you need, probably, cannot be done.

**Attention** This is a public forum