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.

MSP430G2553: MSP430G2553 Capacitive Touch and IR Receiver - Timer Issue

Part Number: MSP430G2553
Other Parts Discussed in Thread: MSP430WARE, MSP430FR2533

We are using the MSP430G2553 , We are using Capacitive touch with 5 keys and we have tested it and working fine. We are using IR receiver RC5 code and we have tested with our remote and it is working fine. When we are using both together IR data receiving getting different value then actual data (when IR working independently - without touch). So we are unable to use the Touch and IR together.

  • is it must to use LPM3 - ?  __bis_SR_register(LPM3_bits);            // changes in sensor C

  • Hi Nilesh,

    It sounds like something in the capacitive touch portion of the code is changing the timing required by the RC5 code.  To help me better understand the issue, what capacitive touch and IR RC5 software are you using?

  • Hi Dennis,

    Thank you for reply. I have attached the code here.

    /* --COPYRIGHT--,BSD_EX
     * Copyright (c) 2012, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     *******************************************************************************
     *
     *                       MSP430 CODE EXAMPLE DISCLAIMER
     *
     * MSP430 code examples are self-contained low-level programs that typically
     * demonstrate a single peripheral function or device feature in a highly
     * concise manner. For this the code may rely on the device's power-on default
     * register values and settings such as the clock configuration and care must
     * be taken when combining code from several examples to avoid potential side
     * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware
     * for an API functional library-approach to peripheral configuration.
     *
     * --/COPYRIGHT--*/
    //******************************************************************************
    //  MSP430G2xx3 Demo - Capacitive Touch, Pin Oscillator Method, 5 buttons, UART
    //
    //  Description: Basic 8-button input using the built-in pin oscillation feature
    //  on GPIO input structure. PinOsc signal feed into TA0CLK. WDT interval is used
    //  to gate the measurements. Difference in measurements indicate button touch.
    //  Pins used for inputs listed in the diagram below.
    //  After each scan, one UART byte identifying the key# being pressed is
    //  transmitted via TimerA UART at port pin P1.1.
    //
    //
    //  ACLK = VLO = 12kHz, MCLK = SMCLK = 1MHz DCO
    //
    //               MSP430G2xx3
    //             -----------------
    //         /|\|                 |  
    //          | |                 |
    //          --|RST              |
    //            |                 |
    //  input 1-->|P2.0         P1.1|--> TA UART output TXD
    //            |                 |
    //  input 2-->|P2.1             |
    //            |                 |
    //  input 3-->|P2.2             |
    //            |                 |
    //  input 4-->|P2.3             |
    //            |                 |
    //  input 5-->|P2.4             |
    //            |                 |
    //             -----------------      All five inputs are capacitive touch inputs      
    //
    //   Brandon Elliott/D. Dang
    //  Texas Instruments Inc.
    //  November 2010
    //   Built with IAR Embedded Workbench Version: 5.10
    //******************************************************************************
    #include <msp430.h>
    // Define User Configuration values
    //----------------------------------
    // Defines WDT SMCLK interval for sensor measurements
    #define WDT_meas_setting (DIV_SMCLK_512)
    // Defines WDT ACLK interval for delay between measurement cycles
    #define WDT_delay_setting (DIV_ACLK_512)

    // Sensor settings
    #define NUM_SEN        5                    // Total number of sensors
    #define KEY_LVL     190                     // Defines threshold for a key press
    // Set to ~ half the max delta expected

    // Definitions for use with the WDT settings
    #define DIV_ACLK_32768  (WDT_ADLY_1000)     // ACLK/32768
    #define DIV_ACLK_8192   (WDT_ADLY_250)      // ACLK/8192
    #define DIV_ACLK_512    (WDT_ADLY_16)       // ACLK/512
    #define DIV_ACLK_64     (WDT_ADLY_1_9)      // ACLK/64
    #define DIV_SMCLK_32768 (WDT_MDLY_32)       // SMCLK/32768
    #define DIV_SMCLK_8192  (WDT_MDLY_8)        // SMCLK/8192
    #define DIV_SMCLK_512   (WDT_MDLY_0_5)      // SMCLK/512
    #define DIV_SMCLK_64    (WDT_MDLY_0_064)    // SMCLK/64

    // Global variables for sensing
    unsigned int base_cnt[NUM_SEN];
    unsigned int meas_cnt[NUM_SEN];
    int delta_cnt[NUM_SEN];
    unsigned char key_press[NUM_SEN];
    char key_pressed;
    int cycles;

    const unsigned char electrode_bit_P2[NUM_SEN]={BIT0, BIT1, BIT2, BIT3, BIT4};
    // System Routines
    void measure_count(void);                   // Measures each capacitive sensor
    void TX_Byte (char);                        // Transmits key pressed via UART
    // Main Function
    // Other Code
    #define IRDATA BIT4             // IR receiver on P1.4
    #define RED BIT0        // Red LED on P1.0
    #define GREEN BIT6            // Green LED on P1.6
    #define MOTOR BIT7
    //#define T_INTERVAL 2450        // Timing between IRDATA samples - should be closer to 1778 with 1MHz clock, but mine runs fast. YMMV
    #define T_INTERVAL 1778        // Timing between IRDATA samples - should be closer to 1778 with 1MHz clock, but mine runs fast. YMMV
    #define DEBUG_PIN BIT3

    int data = 0;                   // Hold the incoming IRDATA stream
    int command = 0;                // The command received
    int address = 0;                // The device address received
    int toggle = 0;                 // The toggle bit from the IRDATA stream

    unsigned char IRTouch =0;


    int main(void)
    {
      unsigned int i,j;
      WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
      if (CALBC1_1MHZ==0xFF)                    // If calibration constant erased
      {                                            
        while(1);                               // do not load, trap CPU!!    
      }
        if (CALBC1_8MHZ==0xFF)                    // If calibration constant erased
      {                                            
        while(1);                               // do not load, trap CPU!!    
      }
      DCOCTL = 0;                               // Select lowest DCOx and MODx settings
      BCSCTL1 = CALBC1_1MHZ;                    // Set DCO to 1MHz
      DCOCTL =  CALDCO_1MHZ;
      BCSCTL3 |= LFXT1S_2;                      // LFXT1 = VLO
     
      BCSCTL2 &= ~SELS;                          // SMCLK source
      //BCSCTL3 |= LFXT1S_2;                // LFXT1 = VLO
      BCSCTL2 |= DIVS_0;                  // Set SMCLK Divider to 1 (1MHz)
     
     
      IE1 |= WDTIE;                             // enable WDT interrupt
      P2SEL = 0x00;                             // No XTAL

     
      /*
       * Set up the I/O pins
       */
      P1REN |= DEBUG_PIN ;                        // pullup resistor for timing debug pin
      P1OUT |= DEBUG_PIN | RED | GREEN;        // Set all these HIGH
      P1DIR |= DEBUG_PIN | RED | GREEN;        // Set all these as outputs
      P1DIR |= MOTOR;
      P1OUT &= ~MOTOR;
      P1DIR &= ~IRDATA;                // IRDATA is an input
      P1IE = IRDATA;                // enable interrupts, watching IRDATA for a change
      P1IES = IRDATA;                // watch for falling edge change on IRDATA

      //TACCR0 = T_INTERVAL;                // Set the timing interval for TimerA
      TA1CCR0 =  T_INTERVAL;               // timer1

       __bis_SR_register(GIE);                  // Enable interrupts

      measure_count();                          // Establish baseline capacitance
      for (i = 0; i<NUM_SEN; i++)
        base_cnt[i] = meas_cnt[i];

      for(i=15; i>0; i--)                       // Repeat and avg base measurement
      {
        measure_count();
        for (j = 0; j<NUM_SEN; j++)
          base_cnt[j] = (meas_cnt[j]+base_cnt[j])/2;
      }
     
      // Main loop starts here
      while (1)
      {
        
        if( IRTouch == 1 )
        {
          j = KEY_LVL;
          measure_count();                        // Measure all sensors
          for (i = 0; i<NUM_SEN; i++)
          {
            // Handle baseline measurment for a base C decrease
            if (base_cnt[i] < meas_cnt[i])        // If negative: result increased
            {                                     // beyond baseline, cap decreased
              base_cnt[i] = (base_cnt[i]+meas_cnt[i]) >> 1; // Re-average up quickly
              delta_cnt[i] = 0;                 // Zero out for position determination
            }
            else
            {
              delta_cnt[i] = base_cnt[i] - meas_cnt[i];  // Calculate delta: c_change
            }
            if (delta_cnt[i] > j)                 // Determine if each key is pressed
            {                                     // per a preset threshold
              key_press[i] = 1;                   // Specific key pressed
              j = delta_cnt[i];
              key_pressed = i+1;                  // key pressed        
            }
            else
              key_press[i] = 0;
          }

          // Delay to next sample, sample more slowly if no keys are pressed
          if (key_pressed)
          {
             //TX_Byte(key_pressed);
            BCSCTL1 = (BCSCTL1 & 0x0CF) + DIVA_0; // ACLK/(0:1,1:2,2:4,3:8)
            cycles = 20;
          }
          else
          {
            cycles--;
            if (cycles > 0)                       // ACLK/(0:1,1:2,2:4,3:8)
              BCSCTL1 = (BCSCTL1 & 0x0CF) + DIVA_0;
            else
            {                                     // ACLK/(0:1,1:2,2:4,3:8)  
              BCSCTL1 = (BCSCTL1 & 0x0CF) + DIVA_3;
              cycles = 0;
            }
          }
          WDTCTL = WDT_delay_setting;             // WDT, ACLK, interval timer

          // Handle baseline measurment for a base C increase
          if (!key_pressed)                       // adjust down if no keys touched
          {
            for (i = 0; i<NUM_SEN; i++)
              base_cnt[i] = base_cnt[i] - 1;      // Adjust baseline down, should be
          }                                       // slow to accomodate for genuine
          __bis_SR_register(LPM3_bits);            // changes in sensor C
        }
      }
    }                                           // End Main

    // Measure count result (capacitance) of each sensor
    // Routine setup for four sensors, not dependent on NUM_SEN value!
    void measure_count(void)
    {
      char i;
      TA0CTL = TASSEL_3+MC_2;                   // TACLK, cont mode
      TA0CCTL1 = CM_3+CCIS_2+CAP;               // Pos&Neg,GND,Cap

      for (i = 0; i<NUM_SEN; i++)
      {
        //Configure Ports for relaxation oscillator
        //The P2SEL2 register allows Timer_A to receive it's clock from a GPIO
        //See the Application Information section of the device datasheet for info
        P2DIR &= ~ electrode_bit_P2[i];         
        P2SEL &= ~ electrode_bit_P2[i];         
        P2SEL2 |= electrode_bit_P2[i];          // input oscillation feeds TACLK
        //  Setup Gate Timer
        WDTCTL = WDT_meas_setting;              // WDT, ACLK, interval timer
        TA0CTL |= TACLR;                        // Clear Timer_A TAR
        __bis_SR_register(LPM0_bits+GIE);       // Wait for WDT interrupt
        TA0CCTL1 ^= CCIS0;                      // Create SW capture of CCR1
        meas_cnt[i] = TACCR1;                   // Save result
        WDTCTL = WDTPW + WDTHOLD;               // Stop watchdog timer
        P2SEL2 &= ~electrode_bit_P2[i];
      }
      TA0CTL = 0;                             // Stop Timer_A
    }

    // Watchdog Timer interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=WDT_VECTOR
    __interrupt void watchdog_timer(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(WDT_VECTOR))) watchdog_timer (void)
    #else
    #error Compiler not supported!
    #endif
    {
      TA0CCTL1 ^= CCIS0;                        // Create SW capture of CCR1
      __bic_SR_register_on_exit(LPM3_bits);     // Exit LPM3 on reti
    }
     

    // UART Information: Conditions for 9600 Baud SW TX-only UART, SMCLK = 8MHz
    //#define Bitime    0x0341                    // x us bit length ~ x baud
    //#define TXD       BIT1                      // TXD on P1.1
    //unsigned int RXTXData;
    //unsigned char BitCnt;
    void TX_Byte (char TX_DATA)
    {
    }

    // Timer A0 interrupt service routine
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer0(void)
    {
        __bic_SR_register_on_exit(LPM0_bits);
    }



    #pragma vector = PORT1_VECTOR
    __interrupt void Port_1(void)
    {
      IRTouch = 0;
      //DCOCTL = 0;                               // Select lowest DCOx and MODx settings
      //BCSCTL1 = CALBC1_1MHZ;                    // return DCO to 1MHz
      //DCOCTL =  CALDCO_1MHZ;
      P1IE &= ~IRDATA;                // Turn off P1 interrupts while we work
      P1IFG &= ~IRDATA;                // clear the P1 interrupt flag for IRDATA
      data = 1;                          // first start bit, inverted from receiver
      //data = 0;                          // first start bit, inverted from receiver
      //TODO: wait for second start bit within T_INTERVAL; abandon if it doesn't come.
      // start timer
      //TACCTL0 |= CCIE;                // enable timer interrupts
      //TACTL = TASSEL_2;               // TimerA0 clock selection - SMCLK
      //TACCR0 &= ~CCIFG;                // clear any pending timerA interrrupt flags
      //TACTL |= MC_1;                // start the timer in UP mode
     
     // start timer
      TA1CCTL0 |= CCIE;                // enable timer interrupts
      TA1CTL = TASSEL_2;                       // TimerA1 clock selection - SMCLK
      TA1CCR0 &= ~CCIFG;                // clear any pending timerA interrrupt flags
      TA1CTL |= MC_1;                    // start the timer in UP mode
    }


    #pragma vector = TIMER1_A0_VECTOR
    __interrupt void TimerIR(void)
    {
      /*
       * Need to track the state of a few things... the last toggle bit, the last command issued,
       * the count of how many bits we have parsed.
       */
      static int lastToggle;
      static int lastCommand;
      static char repeat = 0;
      static int count = 0;            // stop after all the bits have been read in

      //TACCTL0 &= ~CCIE;                // clear the interrupt flag
      TA1CCTL0 &= ~CCIE;                // clear the interrupt flag

      if (count >= 13)
      {                // all bits read in and shifted into the data variable
        //TACTL &= MC_0;                // stop the timer
        //TACTL |= TACLR;                // clear the timer settings to zero it out
        TA1CTL &= MC_0;                // stop the timer
        TA1CTL |= TACLR;                // clear the timer settings to zero it out

        command = data & 0x3F;        
        address = (data >> 6) & 0x1F ;
        toggle = (data >> 11) & 1;

        count = 0;


        if (lastCommand == command && lastToggle == toggle)
        {    
          // if we only want one toggle per keypress
          repeat = 1;
        }
        else
        {
          lastCommand = command;
          lastToggle = toggle;
          repeat = 0;
        }
              
        switch (command)
        {            // do whatever we want to do with the incoming commands
          case 0:
                  if (!repeat)
                          P1OUT ^= RED;        // toggle the red LED when the 0 button is pressed
                  break;
          case 1:
                  if (!repeat)
                          P1OUT ^= GREEN;        // toggle the green LED when the 1 button is pressed
                  break;
          case 7:
                  if (!repeat)
                          P1OUT ^= MOTOR;
                  break;
        }
        IRTouch = 1;
        
        P1IE |= IRDATA;                // we have our IR command, reset and start listening for the next one
        P1IFG &= ~IRDATA;
      }
      else
      {
        // read IRDATA and store the value in DATA
        P1OUT &= ~DEBUG_PIN;        // uncomment this and the one a few lines down to see P1.3 toggle with each sample of IRDATA. Use a two channel oscilloscope to adjust T_INTERVAL as necessary.
        if (data > 0)
          data <<= 1;    // shift left one bit
        if ((P1IN & IRDATA) != IRDATA)
        {  
          // invert IRDATA if it is low, because the receiver is active low - append 'data' with a 1
          data |= 1;
        }
        P1OUT |= DEBUG_PIN;       // as above, uncomment for timing debug use
        count++;                    
        //TACCTL0 |= CCIE;            // turn the timer interrupts back on for the next bit
        TA1CCTL0 |= CCIE;            // turn the timer interrupts back on for the next bit
      }
    }

  • Hi Dennis,

    I think following part is changing

    // Delay to next sample, sample more slowly if no keys are pressed
          if (key_pressed)
          {
             //TX_Byte(key_pressed);
            BCSCTL1 = (BCSCTL1 & 0x0CF) + DIVA_0; // ACLK/(0:1,1:2,2:4,3:8)
            cycles = 20;
          }
          else
          {
            cycles--;
            if (cycles > 0)                       // ACLK/(0:1,1:2,2:4,3:8)
              BCSCTL1 = (BCSCTL1 & 0x0CF) + DIVA_0;
            else
            {                                     // ACLK/(0:1,1:2,2:4,3:8)  
              BCSCTL1 = (BCSCTL1 & 0x0CF) + DIVA_3;
              cycles = 0;
            }
          }

  • Hi Dennis,

    Apart from this as we are facing issue , we are also trying on MSP430FR2533 , so just wanted to confirm that with CapTivate we can use other timers without any conflict with CapTivate touch timer ?  Basically we want to add IR remote and few other Timer based function and Buzzer etc . Kindly confirm.

    Regards,

    Nilesh

  • Hi Nilesh,

    I don't think I can isolate the problem you are having with the G2553.  On the MSP430FR2533 the captivate timer is completely independent of the other timers in the MCU so they can be used for whatever purpose.

  • Yes.. we have already started development on the MSP430FR2533 and board bring-up done ! If anything  I will contact you.

    Thank you for your support.

**Attention** This is a public forum