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.

interrupt handling in infinite loop

Other Parts Discussed in Thread: MSP430G2553

Hi,

    I am currently working on 'Face Recognition' which requires LCD to be interfaced with the MSP430G2553. I have to display a message repeatedly. So i am planning to have a code as under

    while(1)
       {
           ClearLcmScreen();
           PrintStr("Press LOGIN to  start logging in");    // main program starts
           // __delay_cycles(1000000);
           _BIS_SR (LPM3_bits + GIE);
           Decision();
       }

First the main string is displayed then the msp goes into sleep mode. when any person presses the LOGIN button the msp wakes and initiates decision function.

After the decision function gets over, the msp must again go back to orignal mode and display "Press LOGIN". and again the process repeates.

#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{
    
}

In the ISR i want to turn off the sleep mode and start active mode.

This is my program code.

//
// MSP430 LCD Code
//

#include  "msp430g2553.h"

// Defining ports for LCM
#define     LCM_DIR               P1DIR
#define     LCM_OUT               P1OUT
// Defining ports for BUTTONS
#define		BUT_DIR				  P2DIR
#define     BUT_IN				  P2IN

//
// Define symbolic LCM - MCU pin mappings
// We've set DATA PIN TO 4,5,6,7 for easy translation
//
#define     LCM_PIN_RS            BIT0          // P1.0
#define     LCM_PIN_EN            BIT1          // P1.1
#define     LCM_PIN_D7            BIT7          // P1.7
#define     LCM_PIN_D6            BIT6          // P1.6
#define     LCM_PIN_D5            BIT5          // P1.5
#define     LCM_PIN_D4            BIT4          // P1.4

// Define symbolic BUTTON - MCU mapping
// we've set ports p2.0,p2.1,p2.2 as input ports
#define		BUT_PIN_T1			  BIT0			// P2.0
#define		BUT_PIN_T2			  BIT1			// P2.1
#define		ENROLL				  BIT2			// P2.2
#define		LOGIN				  BIT3			// P2.3

#define     LCM_PIN_MASK  (LCM_PIN_RS | LCM_PIN_EN | LCM_PIN_D7 | LCM_PIN_D6 | LCM_PIN_D5 | LCM_PIN_D4)
#define		BUT_PIN_MASK  (BUT_PIN_T1 | BUT_PIN_T2 | ENROLL | LOGIN)

#define     FALSE                 0
#define     TRUE                  1

//
// Routine Desc:
//
// This is the function that must be called
// whenever the LCM needs to be told to
// scan it's data bus.
//
// Parameters:
//
//     void.
//
// Return
//
//     void.
//
void PulseLcm()
{
    //
    // pull EN bit low
    //
    LCM_OUT &= ~LCM_PIN_EN;
    __delay_cycles(200);

    //
    // pull EN bit high
    //
    LCM_OUT |= LCM_PIN_EN;
    __delay_cycles(200);

    //
    // pull EN bit low again
    //
    LCM_OUT &= (~LCM_PIN_EN);
    __delay_cycles(200);
}



//
// Routine Desc:
//
// Send a byte on the data bus in the 4 bit mode
// This requires sending the data in two chunks.
// The high nibble first and then the low nible
//
// Parameters:
//
//    ByteToSend - the single byte to send
//
//    IsData - set to TRUE if the byte is character data
//                  FALSE if its a command
//
// Return
//
//     void.
//
void SendByte(char ByteToSend, int IsData)
{
    //
    // clear out all pins
    //
    LCM_OUT &= (~LCM_PIN_MASK);
    //
    // set High Nibble (HN) -
    // usefulness of the identity mapping
    // apparent here. We can set the
    // DB7 - DB4 just by setting P1.7 - P1.4
    // using a simple assignment
    //
    LCM_OUT |= (ByteToSend & 0xF0);

    if (IsData == TRUE)
    {
        LCM_OUT |= LCM_PIN_RS;
    }
    else
    {
        LCM_OUT &= ~LCM_PIN_RS;
    }

    //
    // we've set up the input voltages to the LCM.
    // Now tell it to read them.
    //
    PulseLcm();
     //
    // set Low Nibble (LN) -
    // usefulness of the identity mapping
    // apparent here. We can set the
    // DB7 - DB4 just by setting P1.7 - P1.4
    // using a simple assignment
    //
    LCM_OUT &= (~LCM_PIN_MASK);
    LCM_OUT |= ((ByteToSend & 0x0F) << 4);

    if (IsData == TRUE)
    {
        LCM_OUT |= LCM_PIN_RS;
    }
    else
    {
        LCM_OUT &= ~LCM_PIN_RS;
    }

    //
    // we've set up the input voltages to the LCM.
    // Now tell it to read them.
    //
    PulseLcm();
}


//
// Routine Desc:
//
// Set the position of the cursor on the screen
//
// Parameters:
//
//     Row - zero based row number
//
//     Col - zero based col number
//
// Return
//
//     void.
//
void LcmSetCursorPosition(char Row, char Col)
{
    char address;

    //
    // construct address from (Row, Col) pair
    //
    if (Row == 0)
    {
        address = 0;
    }
    else
    {
        address = 0x40;
    }

    address |= Col;

    SendByte(0x80 | address, FALSE);
}


//
// Routine Desc:
//
// Clear the screen data and return the
// cursor to home position
//
// Parameters:
//
//    void.
//
// Return
//
//     void.
//
void ClearLcmScreen()
{
    //
    // Clear display, return home
    //
	__delay_cycles(20000);
    SendByte(0x01, FALSE);
    __delay_cycles(2000);
    SendByte(0x02, FALSE);
    __delay_cycles(20000);
}


//
// Routine Desc:
//
// Initialize the LCM after power-up.
//
// Note: This routine must not be called twice on the
//           LCM. This is not so uncommon when the power
//           for the MCU and LCM are separate.
//
// Parameters:
//
//    void.
//
// Return
//
//     void.
//
void InitializeLcm(void)
{
    //
    // set the MSP pin configurations
    // and bring them to low
    //
    LCM_DIR |= LCM_PIN_MASK;
    LCM_OUT &= ~(LCM_PIN_MASK);


    //
    // wait for the LCM to warm up and reach
    // active regions. Remember MSPs can power
    // up much faster than the LCM.
    //
    __delay_cycles(100000);


    //
    // initialize the LCM module
    //
    // 1. Set 4-bit input
    //
    LCM_OUT &= ~LCM_PIN_RS;
    LCM_OUT &= ~LCM_PIN_EN;

    LCM_OUT = 0x20;
    PulseLcm();

    //
    // set 4-bit input - second time.
    // (as reqd by the spec.)
    //
    SendByte(0x28, FALSE);

    //
    // 2. Display on, cursor on, blink cursor
    //
    SendByte(0x0F, FALSE);

    //
    // 3. Cursor move auto-increment
    //
    SendByte(0x06, FALSE);
    __delay_cycles(500);

    SendByte(0x80,FALSE);

}

//
// Routine Desc
//
// Initializes the Buttons so that input can be taken
//
// Parameters:
//
//    void
//
// Returns
//
//     void.
//
void InitializeBut()
{	BUT_DIR &= ~(BUT_PIN_MASK);
	BUT_IN &= BUT_PIN_MASK;
	P2IE |= LOGIN;                  // Interrupt Enable in P2.3
	P2IES &= ~LOGIN;                // P2.3 Interrupt flag low-to-high transition
	P2IFG &= ~LOGIN; 			   // P2.3 IFG cleared
}


//
// Routine Desc
//
// Print a string of characters to the screen
//
// Parameters:
//
//    Text - null terminated string of chars
//
// Returns
//
//     void.
//
void PrintStr(char *Text)
{
    char *c;

    c = Text;
     unsigned short int n=0;

     while ((c != 0) && (*c != 0))
    	 {	if(n>15)
    	 	 {
    		 LcmSetCursorPosition(1,n-16);

    	 	 }
    	 	SendByte(*c,TRUE);
    	 	__delay_cycles(305000);
    	 	    	 	 c++;
    	 	    	 	 n++;
    	 }
}

//
// Routine Desc
//
// Print a string of characters to the screen according to the value of buttons
//
// Parameters:
//
//     void
//
// Returns
//
//     void.
//
void Decision()
{
		if ((BUT_IN & BUT_PIN_T1) == BUT_PIN_T1)
		{
			if ((BUT_IN & BUT_PIN_T2) == BUT_PIN_T2)
				{ 	ClearLcmScreen();
					PrintStr("Face recognized  Access Granted");
					__delay_cycles(1000000);
				}
			else
   	    		{	ClearLcmScreen();
   	    			PrintStr("unknown face    like object");
   	    			__delay_cycles(1000000);
   	    		}
		}

		else
   	    {
			if ((BUT_IN & BUT_PIN_T2) == BUT_PIN_T2)
			{	ClearLcmScreen();
   	    		PrintStr("unknown face");
   	    		__delay_cycles(1005000);
   	    		ClearLcmScreen();
   	    		PrintStr("You can be added to the database");
   	    		__delay_cycles(1005000);
   	    		ClearLcmScreen();
   	    		PrintStr("Press ENROLL to start enrolling");
   	    		__delay_cycles(5005000);
   	    			// put a button pressing routine here
   	    		if ((BUT_IN & ENROLL) == ENROLL)
   	    		{
   	    				ClearLcmScreen();
   	        			PrintStr("u pressed ENROLL...enrolling....");
   	        			__delay_cycles(1000000);
   	        			ClearLcmScreen();
   	        			PrintStr("image enrolled");
   	        			__delay_cycles(1000000);
   	        	}
   	    		else
   	        	{	ClearLcmScreen();
   	        		PrintStr("access denied");
   	        		__delay_cycles(1000000);
   	        	}
   	       }
   	    else
   	    	{	ClearLcmScreen();
   	    		PrintStr("unknown object");
   	    		__delay_cycles(1000000);
   	    	}
   	    }
	//	ClearLcmScreen();
	//	PrintStr("Press LOGIN to  login again");
	//	__delay_cycles(5000000);
}


// Port2 Interrupt Service Routine
#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{

}



//
// Routine Desc
//
// main entry point to the sketch
//
// Parameters
//
//     void.
//
// Returns
//
//     void.
//
void main(void)
{

    WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer

    InitializeLcm();					// initializes the LCM
    InitializeBut();					// initializes the buttons for now
    									// in fact it contains inputs from DSP
    ClearLcmScreen();					// clears the LCM screen

    PrintStr("   Welcome to       Bio Recs");
    __delay_cycles(1000000);

   	while(1)
   	{
   		ClearLcmScreen();
   		PrintStr("Press LOGIN to  start logging in");	// main program starts
   		// __delay_cycles(1000000);
   		_BIS_SR (LPM3_bits + GIE);
   		Decision();
   	}






   	//if ((BUT_IN & LOGIN) == LOGIN)		// put an interrupt here so that only
   										// decision is called when interrupted
    //		{	__delay_cycles(1000000);
    //			Decision();

    //		}


}

Can the PORT2 have 2 interrupts? If yes then how to prioritize them?

I am planning to put 2 push buttons for interrupts.

  • lovelesh said:
    In the ISR i want to turn off the sleep mode and start active mode.

    The command to exit sleep mode would be LPM3_EXIT (or if you really want to use the intrinsic it would be something like _BIC_SR(LPM3_bits) ). 

    If you want to you could set a global flag or count in the ISR and then clear or decrement it in Decision() when you start to process the event.  Then test this value before you go back to sleep - only go to sleep if it is clear or zero.  This would help to reduce missing button presses during the processing if this is the kind of operation you want.

    lovelesh said:
    Can the PORT2 have 2 interrupts?

    Yes, you just need to enable all the interrupts you want by setting the bits in the P2IE register.  All the interrupts will go to the same vector (prompt the same ISR).  You need to test the IFG for the pin(s) and clear the bit(s) to prevent the ISR being run continuously.

    lovelesh said:
    If yes then how to prioritize them?

    How do you want to prioritise them?!

    If both events prompt the same action then perhaps you don't need to prioritise them?

    If each event should be fully processed before the other starts then set a global value in the ISR to be processed in the foreground, only update the value in the ISR if it is clear.

    If button1 needs to over-rule any action currently in progress from button2 then it gets more complicated - I'd avoid this if possible!

  • Hi Chris,

                   I changed the ISR as per your instructions. But nothing is happening. The ISR is started every time in debugging mode and the program is struck on the ISR and does not process further. I am attaching my changed file

    //
    // MSP430 LCD Code
    //
    
    #include  "msp430g2553.h"
    
    // Defining ports for LCM
    #define     LCM_DIR               P1DIR
    #define     LCM_OUT               P1OUT
    // Defining ports for BUTTONS
    #define		BUT_DIR				  P2DIR
    #define     BUT_IN				  P2IN
    
    //
    // Define symbolic LCM - MCU pin mappings
    // We've set DATA PIN TO 4,5,6,7 for easy translation
    //
    #define     LCM_PIN_RS            BIT0          // P1.0
    #define     LCM_PIN_EN            BIT1          // P1.1
    #define     LCM_PIN_D7            BIT7          // P1.7
    #define     LCM_PIN_D6            BIT6          // P1.6
    #define     LCM_PIN_D5            BIT5          // P1.5
    #define     LCM_PIN_D4            BIT4          // P1.4
    
    // Define symbolic BUTTON - MCU mapping
    // we've set ports p2.0,p2.1,p2.2 as input ports
    #define		BUT_PIN_T1			  BIT0			// P2.0
    #define		BUT_PIN_T2			  BIT1			// P2.1
    #define		ENROLL				  BIT2			// P2.2
    #define		LOGIN				  BIT3			// P2.3
    
    #define     LCM_PIN_MASK  (LCM_PIN_RS | LCM_PIN_EN | LCM_PIN_D7 | LCM_PIN_D6 | LCM_PIN_D5 | LCM_PIN_D4)
    #define		BUT_PIN_MASK  (BUT_PIN_T1 | BUT_PIN_T2 | ENROLL | LOGIN)
    
    #define     FALSE                 0
    #define     TRUE                  1
    
    //
    // Routine Desc:
    //
    // This is the function that must be called
    // whenever the LCM needs to be told to
    // scan it's data bus.
    //
    // Parameters:
    //
    //     void.
    //
    // Return
    //
    //     void.
    //
    void PulseLcm()
    {
        //
        // pull EN bit low
        //
        LCM_OUT &= ~LCM_PIN_EN;
        __delay_cycles(200);
    
        //
        // pull EN bit high
        //
        LCM_OUT |= LCM_PIN_EN;
        __delay_cycles(200);
    
        //
        // pull EN bit low again
        //
        LCM_OUT &= (~LCM_PIN_EN);
        __delay_cycles(200);
    }
    
    
    
    //
    // Routine Desc:
    //
    // Send a byte on the data bus in the 4 bit mode
    // This requires sending the data in two chunks.
    // The high nibble first and then the low nible
    //
    // Parameters:
    //
    //    ByteToSend - the single byte to send
    //
    //    IsData - set to TRUE if the byte is character data
    //                  FALSE if its a command
    //
    // Return
    //
    //     void.
    //
    void SendByte(char ByteToSend, int IsData)
    {
        //
        // clear out all pins
        //
        LCM_OUT &= (~LCM_PIN_MASK);
        //
        // set High Nibble (HN) -
        // usefulness of the identity mapping
        // apparent here. We can set the
        // DB7 - DB4 just by setting P1.7 - P1.4
        // using a simple assignment
        //
        LCM_OUT |= (ByteToSend & 0xF0);
    
        if (IsData == TRUE)
        {
            LCM_OUT |= LCM_PIN_RS;
        }
        else
        {
            LCM_OUT &= ~LCM_PIN_RS;
        }
    
        //
        // we've set up the input voltages to the LCM.
        // Now tell it to read them.
        //
        PulseLcm();
         //
        // set Low Nibble (LN) -
        // usefulness of the identity mapping
        // apparent here. We can set the
        // DB7 - DB4 just by setting P1.7 - P1.4
        // using a simple assignment
        //
        LCM_OUT &= (~LCM_PIN_MASK);
        LCM_OUT |= ((ByteToSend & 0x0F) << 4);
    
        if (IsData == TRUE)
        {
            LCM_OUT |= LCM_PIN_RS;
        }
        else
        {
            LCM_OUT &= ~LCM_PIN_RS;
        }
    
        //
        // we've set up the input voltages to the LCM.
        // Now tell it to read them.
        //
        PulseLcm();
    }
    
    
    //
    // Routine Desc:
    //
    // Set the position of the cursor on the screen
    //
    // Parameters:
    //
    //     Row - zero based row number
    //
    //     Col - zero based col number
    //
    // Return
    //
    //     void.
    //
    void LcmSetCursorPosition(char Row, char Col)
    {
        char address;
    
        //
        // construct address from (Row, Col) pair
        //
        if (Row == 0)
        {
            address = 0;
        }
        else
        {
            address = 0x40;
        }
    
        address |= Col;
    
        SendByte(0x80 | address, FALSE);
    }
    
    
    //
    // Routine Desc:
    //
    // Clear the screen data and return the
    // cursor to home position
    //
    // Parameters:
    //
    //    void.
    //
    // Return
    //
    //     void.
    //
    void ClearLcmScreen()
    {
        //
        // Clear display, return home
        //
    	__delay_cycles(20000);
        SendByte(0x01, FALSE);
        __delay_cycles(2000);
        SendByte(0x02, FALSE);
        __delay_cycles(20000);
    }
    
    
    //
    // Routine Desc:
    //
    // Initialize the LCM after power-up.
    //
    // Note: This routine must not be called twice on the
    //           LCM. This is not so uncommon when the power
    //           for the MCU and LCM are separate.
    //
    // Parameters:
    //
    //    void.
    //
    // Return
    //
    //     void.
    //
    void InitializeLcm(void)
    {
        //
        // set the MSP pin configurations
        // and bring them to low
        //
        LCM_DIR |= LCM_PIN_MASK;
        LCM_OUT &= ~(LCM_PIN_MASK);
    
    
        //
        // wait for the LCM to warm up and reach
        // active regions. Remember MSPs can power
        // up much faster than the LCM.
        //
        __delay_cycles(100000);
    
    
        //
        // initialize the LCM module
        //
        // 1. Set 4-bit input
        //
        LCM_OUT &= ~LCM_PIN_RS;
        LCM_OUT &= ~LCM_PIN_EN;
    
        LCM_OUT = 0x20;
        PulseLcm();
    
        //
        // set 4-bit input - second time.
        // (as reqd by the spec.)
        //
        SendByte(0x28, FALSE);
    
        //
        // 2. Display on, cursor on, blink cursor
        //
        SendByte(0x0F, FALSE);
    
        //
        // 3. Cursor move auto-increment
        //
        SendByte(0x06, FALSE);
        __delay_cycles(500);
    
        SendByte(0x80,FALSE);
    
    }
    
    //
    // Routine Desc
    //
    // Initializes the Buttons so that input can be taken
    //
    // Parameters:
    //
    //    void
    //
    // Returns
    //
    //     void.
    //
    void InitializeBut()
    {	BUT_DIR &= ~(BUT_PIN_MASK);
    	BUT_IN &= BUT_PIN_MASK;
    	P2IE |= LOGIN;                  // Interrupt Enable in P2.3
    	P2IES &= ~LOGIN;                // P2.3 Interrupt flag low-to-high transition
    	P2IFG &= ~LOGIN; 			   // P2.3 IFG cleared
    
    }
    
    
    //
    // Routine Desc
    //
    // Print a string of characters to the screen
    //
    // Parameters:
    //
    //    Text - null terminated string of chars
    //
    // Returns
    //
    //     void.
    //
    void PrintStr(char *Text)
    {
        char *c;
    
        c = Text;
         unsigned short int n=0;
    
         while ((c != 0) && (*c != 0))
        	 {	if(n>15)
        	 	 {
        		 LcmSetCursorPosition(1,n-16);
    
        	 	 }
        	 	SendByte(*c,TRUE);
        	 	__delay_cycles(305000);
        	 	    	 	 c++;
        	 	    	 	 n++;
        	 }
    }
    
    //
    // Routine Desc
    //
    // Print a string of characters to the screen according to the value of buttons
    //
    // Parameters:
    //
    //     void
    //
    // Returns
    //
    //     void.
    //
    void Decision()
    {
    		if ((BUT_IN & BUT_PIN_T1) == BUT_PIN_T1)
    		{
    			if ((BUT_IN & BUT_PIN_T2) == BUT_PIN_T2)
    				{ 	ClearLcmScreen();
    					PrintStr("Face recognized  Access Granted");
    					__delay_cycles(1000000);
    				}
    			else
       	    		{	ClearLcmScreen();
       	    			PrintStr("unknown face    like object");
       	    			__delay_cycles(1000000);
       	    		}
    		}
    
    		else
       	    {
    			if ((BUT_IN & BUT_PIN_T2) == BUT_PIN_T2)
    			{	ClearLcmScreen();
       	    		PrintStr("unknown face");
       	    		__delay_cycles(1005000);
       	    		ClearLcmScreen();
       	    		PrintStr("You can be added to the database");
       	    		__delay_cycles(1005000);
       	    		ClearLcmScreen();
       	    		PrintStr("Press ENROLL to start enrolling");
       	    		__delay_cycles(5005000);
       	    			// put a button pressing routine here
       	    		if ((BUT_IN & ENROLL) == ENROLL)
       	    		{
       	    				ClearLcmScreen();
       	        			PrintStr("u pressed ENROLL...enrolling....");
       	        			__delay_cycles(1000000);
       	        			ClearLcmScreen();
       	        			PrintStr("image enrolled");
       	        			__delay_cycles(1000000);
       	        	}
       	    		else
       	        	{	ClearLcmScreen();
       	        		PrintStr("access denied");
       	        		__delay_cycles(1000000);
       	        	}
       	       }
       	    else
       	    	{	ClearLcmScreen();
       	    		PrintStr("unknown object");
       	    		__delay_cycles(1000000);
       	    	}
       	    }
    	//	ClearLcmScreen();
    	//	PrintStr("Press LOGIN to  login again");
    	//	__delay_cycles(5000000);
    }
    
    
    // Port2 Interrupt Service Routine
    #pragma vector=PORT2_VECTOR
    __interrupt void Port_2(void)
    {
    	_BIC_SR(LPM3_bits);
    	//LPM3_EXIT;
    }
    
    
    
    //
    // Routine Desc
    //
    // main entry point to the sketch
    //
    // Parameters
    //
    //     void.
    //
    // Returns
    //
    //     void.
    //
    void main(void)
    {
    
        WDTCTL = WDTPW + WDTHOLD;             // Stop watchdog timer
    
        InitializeLcm();					// initializes the LCM
        InitializeBut();					// initializes the buttons for now
        									// in fact it contains inputs from DSP
        ClearLcmScreen();					// clears the LCM screen
    
        PrintStr("   Welcome to       Bio Recs");
        __delay_cycles(1000000);
    
       	while(1)
       	{
       		ClearLcmScreen();
       		PrintStr("Press LOGIN to  start logging in");	// main program starts
       		// __delay_cycles(1000000);
       		_BIS_SR (LPM3_bits + GIE);
       		Decision();
       		P2IFG &= ~LOGIN; 			   // P2.3 IFG cleared
    
       	}
    
    
    
    
    
    
       	//if ((BUT_IN & LOGIN) == LOGIN)		// put an interrupt here so that only
       										// decision is called when interrupted
        //		{	__delay_cycles(1000000);
        //			Decision();
    
        //		}
    
    
    }
    

    Can I send u an image of my connection? So that you can get better idea of the problem.

    Can you explain more on placing a counter and checking it?

  • chris_m said:
    it would be something like _BIC_SR(LPM3_bits)

    Oops.  It needs to clear the bits in the copy of the SR on the stack not the current SR - it'll be a command like _BIC_SR_ON_EXIT.  Sorry I always use the LPM3 and LPM3_EXIT commands.

  • You need to clear the IFG otherwise the ISR will just keep getting called over and over.

    Also you need to use LPM3_EXIT or BIC_SR_ON_EXIT in order to exit the sleep mode (see my previous post - sorry about that!)

  • Hi Chris,

                    I tried LPM3_EXIT but the program never leaves ISR. It gets struck on the ISR. So the decision function in never called. Your _BIC_SR_ON_EXIT is undefined.

  • Have you added the command to clear the interrupt flag?  As I said before you need to clear the IFG to stop the ISR being called continuously.

    P2IFG = 0 will clear all the flags or use P2IFG &= ~BITx to clear an individual flag if you were wanting to process the buttons separately.

  • thnx chris, it worked now the program is working fine.

  • I'm glad it's working.

    lovelesh said:
    Can you explain more on placing a counter and checking it

    Having read through more of your code now I don't think a counter is very suitable for this application but I'll explain the idea anyway. 

    If the ISR simply wakes up from sleep and the main loop starts to execute, then any button presses that occur while the first event is being processed will not have any effect - the MSP is already awake and will just continue the main loop and then go back to sleep without ever noticing the extra button presses. 

    But if the ISR sets a flag to indicate a button press then the main loop can use a test on this flag - if it is clear then go to sleep and wait but if it is set then don't go to sleep but continue to execute the loop (probably clearing the flag first to indicate it is being processed). 

    Extending this we can use a counter instead.  Have a global variable that is incremented in the ISR everytime the button is pressed.  Now in your main loop you look at the value before going to sleep as with the flag test - if it is zero then it is safe to sleep, otherwise you need to stay awake.  In the main code you can then decrement the counter each time you run the main code.  In this way no events are ever dropped - the main code is always run the same number of times as there were button presses (albeit with some potential latency).  For some situations the main code could change the process depending on the counter value.  For example say you have a variable cDisp which is shown on a display and is incremented every time a button is pressed.  If the button count value bCnt is increment in several quick-succession ISRs and is read in the main code as "5" then instead of running the loop 5 times just add 5 onto cDisp and update the display just once.  The count value bCnt would then be decreased by 5 and tested - if zero then go to sleep etc...

    Hope this makes sense.

    Chris.

  • Thnx Chris, now i am working on detecting the ENROLL button press that i have indicated in my code. I am planning to put a waiting loop that will go on checking the button press for some time. Can u suggest me some codes for it? I am using push button as ENROLL.

  • I have completed debouncing the ENROLL button. I am using a counter to wait for the button press.

    volatile unsigned int i;
                       i=5000;                        //Delay, button debounce
                       do (i--);
                       while (i !=0);

                       while (! (BUT_IN & ENROLL));        //Wait for the release of the button

                       i=5000;                        //Delay, button debounce
                       do (i--);
                       while (i !=0);

    Is there any modifications i can do to make it better? The value 5000 is obtained by trial and error.

**Attention** This is a public forum