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/MSP430FR2355: MSP430FR2355

Part Number: MSP430FR2355

Tool/software: Code Composer Studio

Hello. I am trying to create a system which measures the distance via an ultrasonic sensor. The system gives a signal if the distance is below the minimum distance with putting the red LED(LED1, P1.0) on High and start a speaker which is connected with the system. If the distance is higher than the minimun distance than the system puts the red LED on low and stops the speaker, but puts the green LED(LED2, P6.6) on high. I hope till here the function of my system is clear. These functions i just described are working all fine and give me the right results. Now i want to create a start/stop button(i use the S1, P4.1). This button allows the user to manually start the measuring and stop it. While the system waits for this input it puts itself in sleep mode. So i created an interrupt with the button S1. Now my problem is that as soon i press the button the system begins to measure the distance(so this part works correct) but with pressing the button a second time it wont go back to sleep mode. I know a little bit where the problem is but cant really solve it. The measuring itself is in a while loop therefor it cant leave the loop and end the interrupt. My question is if there is a proper solution so that i can press the button once to start the system to measure the distance an press the button a second time to stop measuring and let the system go back into sleep mode. Any help would be appreciated.

#include "driverlib.h"
#include "rom_driverlib.h"
#include "Board.h"
#include "us_sensor.h"
#include "us_sensor1.h"
#include "piezo.h"


//Target frequency for MCLK in kHz
#define CS_MCLK_DESIRED_FREQUENCY_IN_KHZ   1000
//MCLK/FLLRef Ratio
#define CS_MCLK_FLLREF_RATIO   30

void init_gpio(void);
void init_cs(void);


void main (void)
{

    WDT_A_hold(WDT_A_BASE);     //Stop watchdog timer

    init_gpio();                // Es wird nur LED I/O festgelegt

    init_cs();                  //Initalisiert das Clock-System
                                //mit DCO als Oszillator und ACLK als Taktquelle (wird für US-Sensoren benötigt)

    sr04_init();                //Init us-sensor
    sr04_init1();                //Init us-sensor1

    piezo_init();               //Init Piezo-Speaker
    piezo_stop();

    __bis_SR_register(GIE + LPM0_bits);     //Enable global interrupt


}

void init_gpio(void) {
    //Set LED1 to output direction
    GPIO_setAsOutputPin(
        GPIO_PORT_LED1,
        GPIO_PIN_LED1
        );
    //Set LED2 to output direction
    GPIO_setAsOutputPin(
        GPIO_PORT_LED2,
        GPIO_PIN_LED2
        );
    //Set S1 to input direction with internal pull-up resistance
    GPIO_setAsInputPinWithPullUpResistor(
        GPIO_PORT_S1,
        GPIO_PIN_S1
        );

    GPIO_selectInterruptEdge(
        GPIO_PORT_S1,
        GPIO_PIN_S1,
        GPIO_HIGH_TO_LOW_TRANSITION
        );

    GPIO_clearInterrupt(
        GPIO_PORT_S1,
        GPIO_PIN_S1
        );

    GPIO_enableInterrupt(
        GPIO_PORT_S1,
        GPIO_PIN_S1
        );

    PMM_unlockLPM5();
}

void init_cs(void) {
    //Set DCO FLL reference = REFO
    CS_initClockSignal(
        CS_FLLREF,
        CS_REFOCLK_SELECT,
        CS_CLOCK_DIVIDER_1
        );

    //Set ACLK = REFO
    CS_initClockSignal(
        CS_ACLK,
        CS_REFOCLK_SELECT,
        CS_CLOCK_DIVIDER_1
        );
    
    //Create struct variable to store proper software trim values
    CS_initFLLParam param = {0};
    
    //Set Ratio/Desired MCLK Frequency, initialize DCO, save trim values
    CS_initFLLCalculateTrim(
        CS_MCLK_DESIRED_FREQUENCY_IN_KHZ,
        CS_MCLK_FLLREF_RATIO,
        &param
        );

    //Clear all OSC fault flag
    CS_clearAllOscFlagsWithTimeout(1000);

    //Enable oscillator fault interrupt
    SFR_enableInterrupt(SFR_OSCILLATOR_FAULT_INTERRUPT);
}


#pragma vector=UNMI_VECTOR
__interrupt void NMI_ISR(void)
{
    uint16_t status;
    do {
        // If it still can't clear the oscillator fault flags after the timeout,
        // trap and wait here.
        status = CS_clearAllOscFlagsWithTimeout(1000);
    } while(status != 0);
}


bool flag = false;
#pragma vector=PORT4_VECTOR
__interrupt void Port_4(void)
{
    uint16_t distance;
    uint16_t distance1;
    if ((P4IES & BIT1) == BIT1) {
        // on high to low transition:
        // activate low to high transition: on button release
        P4IES &= ~BIT1;
        GPIO_getInputPinValue(GPIO_PORT_P4, GPIO_PIN1);

        __bis_SR_register(GIE);     //Enable global interrupt

        sr04_start();               // MESSUNG von US-SENSOR
        sr04_start1();               // MESSUNG von US-SENSOR
        while (1)
        {
           distance = sr04_get_value();         //Get distance from US-Sensor1
           distance = distance/2;               //Calculate distance just in one way

           distance1 = sr04_get_value1();       //Get distance from US-Sensor2
           distance1 = distance1/2;             //Calculate distance just in one way


            if((distance <= 1500) || (distance1 <= 1500)) {      //Check minimum distance at 1500mm; if either US1 or US2 is lower than minimum distance
                GPIO_setOutputHighOnPin(GPIO_PORT_LED1, GPIO_PIN_LED1);     //Set LED1 on High
                GPIO_setOutputLowOnPin(GPIO_PORT_LED2, GPIO_PIN_LED2);      //Set LED2 in Low
                piezo_start();                                              //Start Piezo Timer for PWM-Signal
            }
            else {
                piezo_stop();                                               //Stop Piezo Timer from PWM-Signal
                GPIO_setOutputHighOnPin(GPIO_PORT_LED2, GPIO_PIN_LED2);     //Set LED2 on High
                GPIO_setOutputLowOnPin(GPIO_PORT_LED1, GPIO_PIN_LED1);      //Set LED1 on Low
            }


            __no_operation();                   // debugger breakpoint location
        }


    }
    else {
        // on low to high transistion:
        // activate high to low transition: on button press
        P4IES |= BIT1;
    }

    GPIO_clearInterrupt(
            GPIO_PORT_S1,
            GPIO_PIN_S1
            );
}

  • Due to that while(1) loop in the Port4 ISR, once you get the first call (button push) you will never exit the ISR. Since you enabled GIE, subsequent calls (buttons) will call the ISR above this call, but this call will never exit and you'll never return to the LPM0 in main.

    I recommend you move the entire while(1) into main, and don't enable GIE in the ISR. Rather, just set a ("volatile") flag and LPM0_EXIT, then have main check the flag, maybe at the beginning of the while loop.

    More generally, setting GIE in an ISR is quite hazardous. If you ever find yourself about to do this, stop and find some other way to do what you want.

  • Ok, thanks that works. This project is part of my studying and i am really at the beginning of learning with such a environment and that type of coding. Like you said, i put the while loop in the main and set a flag which will now change if i press the button and let the system to start and stop the measuring. I am just at the start with embedded systems, so your comment helped me a lot to understand what i can do and what should i dont do. Again, thank you very much.