简体   繁体   中英

CCS/MSP430FR6989: Capture/Compare Interrupt not working with HR-S04 Ultrasonic Sensor

I am currently trying to interface the HR-S04 Ultrasonic Distance Sensor to the MSP430FR6989. I have found several times over where the code has been written, yet the code that supposedly works for others will not work for me. One difference between my scenario and the scenario that others are seen using is that I do not have an external LCD that I am printing to, and instead I am either trying to display the output to the onboard LCD on the Launchpad, or (since that didn't work for me) I am attempting to write it to the terminal via UART. Below is my code, as well as my guesses to what could potentially be the issue(s):

The idea for the program is that the "low time" is compared to the "high time". This should be done by storing the TA0CCR0 value for the rising and falling edge for each occurrence on the interrupt and do basic arithmetic with those two values.

#include <msp430fr6989.h>

#define redLED BIT0
#define greenLED BIT7

#define US_TRIG         BIT4
#define US_ECHO         BIT5
#define US_MASK         US_TRIG | US_ECHO

#define FLAGS_TERM      UCA1IFG
#define RXFLAG          UCRXIFG
#define TXFLAG          UCTXIFG
#define TERM_TXBUFFER   UCA1TXBUF
#define TERM_RXBUFFER   UCA1RXBUF

unsigned int up_counter = 0,down_counter, distance_cm = 0, count = 0;

void initialize_TERM_UART(void)
{
    P3SEL1 &= ~ (BIT4|BIT5);
    P3SEL0 |= (BIT4|BIT5);
    UCA1CTLW0 |= UCSSEL_2;
    UCA1BRW = 8;
    UCA1MCTLW = UCBRS3 | UCBRS2| UCBRS0 | UCBRS6_H | UCBRS5_H;
    UCA1MCTLW &= ~UCOS16;
    UCA1CTLW0 &= ~ UCSWRST;
    UCA1IE |= UCRXIE;
    UCA1IFG &= ~RXFLAG;
}

void uart_write_char_TERM(unsigned char ch)
{
    // Wait for any ongoing transmission to complete
    while ( (FLAGS_TERM & TXFLAG)==0 ) {}
    // Write the byte to the transmit buffer
    TERM_TXBUFFER = ch;
}

void uart_digit_sep_TERM(unsigned int n)
{
    unsigned int digit;
    if (n >= 10000)
        {
            digit = (n/10000) % 10;
            uart_write_char_TERM(digit + '0');
        }
        else
            uart_write_char_TERM('0');
    if (n >= 1000)
        {
            digit = (n/1000) % 10;
            uart_write_char_TERM(digit + '0');
        }
        else
            uart_write_char_TERM('0');
    if (n >= 100)
    {
        digit = (n/100) % 10;
        uart_write_char_TERM(digit + '0');
    }
    else
        uart_write_char_TERM('0');
    if (n >= 10)
    {
        digit = (n/10) % 10;
        uart_write_char_TERM(digit + '0');
    }
    else
        uart_write_char_TERM('0');

    digit = (n % 10);
    uart_write_char_TERM(digit + '0');
    uart_write_char_TERM(' ');
}

#pragma vector=TIMER0_A0_VECTOR
__interrupt void TimerA0(void)
{
    P1OUT ^= redLED;
    P9OUT ^= greenLED;
    if (TA0CCTL0 & CCI)            // Raising edge
    {
        up_counter = TA0CCR0;      // Copy counter to variable
    }
    else                        // Falling edge
    {
        // Formula: Distance in cm = (Time in uSec)/58
        distance_cm = (TA0CCR0 - up_counter)/58;
        uart_digit_sep_TERM(distance_cm);
    }
    TA0CCTL0 &= ~CCIFG;
    TA0CTL &= ~TAIFG;           // Clear interrupt flag - handled
}
void timer_init()
{
    /* Timer A0 configure to read echo signal:
    Timer A Capture/Compare Control 0 =>
    capture mode: 1 - both edges +
    capture synchronize +
    capture input select 0 => P1.5 +
    capture mode +
    capture compare interrupt enable */
    TA0CCTL0 |= CM_3 + SCS + CCIS_0 + CAP + CCIE;
    TA0CCTL0 &= ~ CCIFG;

    /* Timer A Control configuration =>
    Timer A clock source select: 1 - SMClock +
    Timer A mode control: 2 - Continous up +
    Timer A clock input divider 0 - No divider */
    TA0CTL |= TASSEL_2 + MC_2 + ID_0;
}

int main()
{
    WDTCTL = WDTPW | WDTHOLD;       // Stop Watch Dog Timer
    PM5CTL0 &=  ~LOCKLPM5;

    P1DIR |= redLED + US_TRIG;
    P9DIR |= greenLED;
    P1OUT &= ~(redLED | US_TRIG) ;
    P9OUT |= greenLED;

    P1DIR &= ~US_ECHO;        // Input direction for echo from sensor
    P1SEL1 |= US_ECHO;                // set US_ECHO as trigger for Timer from Port-1
    P1SEL0 |= US_ECHO;

    // Initialize timer for Ultrasonice distance sensing
    timer_init();
    initialize_TERM_UART();
    _enable_interrupts();

    while (1)
    {
        // measuring the distance
        P1OUT |= US_TRIG;                 // assert
        __delay_cycles(15);                 // 10us wide
        P1OUT &= ~US_TRIG;                 // deassert
        //__delay_cycles(60000);            // 60ms measurement cycle
        __delay_cycles(500000);             // 0.5sec measurement cycle
        //uart_digit_sep_TERM(i);
        //i++;
    }

}

When I run the above code with hardware breakpoints set within TimerA0(void) ISR, the breakpoints are never triggered as the program never enters the ISR.
This is my first time using a capture/compare interrupt and so my first thought is that it is possible that I configured the interrupt/timer incorrectly—but this is curious as various others have posted on similar sites saying that the code works for them.
Another idea that I had is that perhaps my timer configuration and UART configuration clash somehow, but that shouldn't affect whether or not the ISR is triggered or not.
Not sure if it helps or not but I'm running CCS 9.2.0.00013 on OSX 10.10.5

I ran the program on a different sensor (I bought them in bulk) and the program works flawlessly. It should be noted that when you buy a bunch of sensors at a discounted rate they will not all be functional.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM