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.

Xbee and MSP430 Interface

Other Parts Discussed in Thread: MSP430F2272

Hello there,

I am trying to interface Xbee DOUT (AP = 2) with MSP430F2272 RX. I use some of the example code from TI which is to use the USCI_A0_RX interrupt. I have these settings:

 WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  BCSCTL1 = CALBC1_1MHZ;                    // Set DCO
  DCOCTL = CALDCO_1MHZ;
  P3SEL = 0x30;                             // P3.4,5 = USCI_A0 TXD/RXD
  UCA0CTL1 |= UCSSEL_2;                     // SMCLK
  UCA0BR0 = 104;                            // 1MHz 9600
  UCA0BR1 = 0;                              // 1MHz 9600
  UCA0MCTL = UCBRS0;                        // Modulation UCBRSx = 1
  UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
  IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt

And the ISR is set up as such:
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
  apiframe[j++] = UCA0RXBUF; 
  if ((j == 0 && UCA0RXBUF == 0x7E) || j > 0) {
    data[j++] = apiframe[j++];
     if (j == 11){  
         dh = apiframe[j];
        }
     if (j == 12) {  
         dl = apiframe[j];
        }
     if (j > sizeof apiframe - 1) { 
         j = 0;
     }
   }
}

The API frame is 14 bytes long (hex): 7E 00 0A 83 00 01 24 00 01 20 00 02 5D D7

However, when I use CCS to debug and view UCA0RXBUF I get nothing remotely close to the API Frame. I am trying to parse the packet and get data dh and dl (some processing and math will be done in a function to output to LCD). In debug dh should be 02 and dl = 5D (byte 11 and 12 of frame).

I also tried doing some simple code to make sure interrupt was firing. The API frame was 7E 00 0A 83 00 01 2F 00 01 00 10 00 10 2B. I had a Endpoint Xbee sample D04 which I set to Digital High and the Coordinator would output the RXed frame onto DOUT which is connected to MSP430 RX. When I use CCS to debug I get apiframe[] = {00, 00, 36, 00, 00, 36, ...}. Whether I have the Coordinator setup to AP = 1 or 2, I get the same which is not right. I also tried polling the register (with the interrupt disables) in the main(), and I get the same for apiframe[].

Please your help is truly appreciated. My graduation depends on this :/

  • Suzanne

    It looks like you are incrementing the variable j too many times.  In the code for the ISR you have

    Suzanne Delica said:

      apiframe[j++] = UCA0RXBUF; 
      if ((j == 0 && UCA0RXBUF == 0x7E) || j > 0) {
        data[j++] = apiframe[j++];

    you read the UCA0RXBUF register and put it into index j and then the post increment operator updates j so the index is now j+1.

    After you enter into the if statement, you try to assign the value in apiframe to the data but the data pointed to by the index is actually one past where the data was placed so you are assigning data which has not been written yet.  I think what you want to assign is the data that was read in the first line.

    Next, the test of UCA0RXBUF == 0x7E causes another access to the UCA0RXBUF register but the first line has already cleared the value from this register.  Reading it again so quickly probably causes an underflow on the UCA0RXBUF register and I'm not sure if the following bytes are actually received or not.  Either way, you should only read the UCA0RXBUF register once per entrance into the ISR.

    Finally, the line of data[j++] = apiframe[j++]; is ambiguous as the point where the variable j is accessed for the two indexes is left up to the compiler.  In effect, the j++ accesses the variable j to get its current value and then increments the value in the variable but uses the value read before the increment.  Since this must happen twice in this statement, we don't know if the index to apiframe the current value of j or j+1, likewise we don't know if the index used for the data array is j+1 or j.  This can change from one compile to the next.

    My suggestion for the code would be something along the following lines

    Suzanne Delica said:

    {
      apiframe[j] = UCA0RXBUF; 
      if ((j == 0 && apiframe[j] == 0x7E) || j > 0) {
        data[j] = apiframe[j];
         if (j == 11){  
             dh = apiframe[j];
            }
         if (j == 12) {  
             dl = apiframe[j];
            }
         if (j > sizeof apiframe - 1) { 
             j = 0;
         }
       }

    j++;

    }

    You may choose to increment j upon entrance but then the test for j==0 would probably never be true.

    You'll have to decide if the remaining tests for values of j are still valid but I think this may get you further along.

    Jim

     

  • Jim,

     

    All I can say is thank you tremendously for replying so quick. That was exactly my problem! you're wonderful!

  • Hello again,

     

    I have another question. Now that the Xbee and MSP430F2272 is in sync. If I update the original code reflecting the ISR changes from above and do not include the Enter LMP0 with interrupt (//__bis_SR_register(LPM0_bits + GIE); ) the interrupt never fires. If I do include it, then the functions in the infinite while never get called. Any suggestions? Thank you!

     WDTCTL = WDTPW + WDTHOLD;   // Stop WDT
       BCSCTL1 = CALBC1_1MHZ;      // Set DCO
       DCOCTL = CALDCO_1MHZ;
      
       P1SEL = 0x00;
       P2SEL = 0x00;
       P3SEL = 0x30;   //P3.4,5 = USCI_A0 TXD/RXD
      
       P1DIR = 0x00;   //set columns P1.0-P1.3 as inputs
       P2DIR = 0x39;   //set rows P2.3 and P2.4, P2.0 for # pressed = LED on, and P2.5 Xbee0 DI0 as outputs
       P3DIR = 0xC0;   //set rows P3.6 and P3.7 as outputs
       P4DIR = 0x10;   //set P4.6 as fancontrol: fancontrol=0 (off); fancontrol=1 (on)

       P3OUT = 0x00;   //initialize output port to ground
       P2OUT = 0x00;
      
       __delay_cycles(100000);
       lcd_init();      //get the lcd booted up
      
      
      //RX Parameters
      UCA0CTL1 |= UCSSEL_2;                     // SMCLK
      UCA0BR0 = 104;                            // 1MHz 9600
      UCA0BR1 = 0;                              // 1MHz 9600
      UCA0MCTL = UCBRS0;                        // Modulation UCBRSx = 1
      UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
      IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt
      //__bis_SR_register(LPM0_bits + GIE);       // Enter LPM0 w/ interrupt
      while (1) {
        //if (dataReady == 1) {
         //IE2 &= ~UCA0RXIE;                          // Disable USCI_A0 RX interrupt
         displayTemp();
         inputTemp();
         //IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt
        //}
        /*else if (dataReady == 0) {  
           lcd_char(0x55);   //U
           lcd_char(0x50);   //P
           lcd_char(0x44);   //D
           lcd_char(0x41);   //A
           lcd_char(0x54);   //T
           lcd_char(0x49);   //I
           lcd_char(0x4E);   //N
           lcd_char(0x47);   //G
           lcd_char(0x2E);   //.
           lcd_char(0x2E);   //.
           lcd_char(0x2E);   //.
             P2OUT |= 0x01; //LED (P2.0) ON
           __delay_cycles(1000000);
           P2OUT &= ~0x01;   //LED (P2.0) OFF
           lcd_command(0x01);   //cursor back to home
           }*/
       //__bis_SR_register(LPM0_bits + GIE);       // Enter LPM0 w/ interrupt
     }
    }

    // Receive RXed character
    #pragma vector=USCIAB0RX_VECTOR
    __interrupt void USCI0RX_ISR(void)
    {
     
         apiframe[j] = UCA0RXBUF;
         if ((j == 0 && apiframe[j] == 0x7E) || j > 0) {
             data[j] = apiframe[j];
         }
         if (j == 11) { 
             dh = data[j];
            }
         if (j == 12) { 
             dl = data[j];
             dataReady = 1;
            }
         if (j > sizeof apiframe - 1) {  
              j = 0;
         }
         j++; 
    }

  • Susanne,

    The main function is entered by default with the GIE bit cleared, i.e. interrupts are disabled.  They only get enabled when you call the function to go into low powaer mode because you include it in the bit mask.  Thus, when you comment out the statement, you never enabled interrupts so the ISR is never entered.  When you leave the line in you enable interrupts and put the system into low power mode so the CPU goes to sleep until the interrupt fires.  When this happens, the processor is woke up and the program counter is pointing to the instruction after where you put it to sleep.  However, because of the interrupt, the processor pushes the program counter and the status register on the stack.  Note that the status register is where the low power mode bits are and the value of the status register pushed on the stack has the low power modes set for LPM0.  Now the ISR runs to completion and at the end an RTI (return from interrupt) instruction is executed which pops the program counter and status register off the stack.  Because the status register has the low power mode bits set, you are returned to low power mode thus the baseline code never executes so none of your functions in the while loop get called.  What you need to do is clear the low power mode bits in the status register on the stack.  You do this by calling an intrinsic function like you used to go into low power mode.  Unfortunately I don't remember exactly what that function is so that's your homework assignment. :)  You should do this before you return from the ISR so that you will return with the processor in active mode.  Then you should be operating as you expect.

    Let me know how things go.

    Jim

     

  • Hey Jim,

     

    I ended up doing some googling and found the fix. I used:

    __bis_SR_register(CPUOFF + GIE);       // Enter LPM0 w/ interrupt

    __bic_SR_register_on_exit(CPUOFF);        // Return to active mode

     

    ***CODE***

    void main(void)
    {
       WDTCTL = WDTPW + WDTHOLD;   // Stop WDT
       BCSCTL1 = CALBC1_1MHZ;      // Set DCO
       DCOCTL = CALDCO_1MHZ;
      
       P1SEL = 0x00;
       P2SEL = 0x00;
       P3SEL = 0x30;   //P3.4,5 = USCI_A0 TXD/RXD
      
       P1DIR = 0x00;   //set columns P1.0-P1.3 as inputs
       P2DIR = 0x39;   //set rows P2.3 and P2.4, P2.0 for # pressed = LED on, and P2.5 Xbee0 DI0 as outputs
       P3DIR = 0xC0;   //set rows P3.6 and P3.7 as outputs
       P4DIR = 0x10;   //set P4.6 as fancontrol: fancontrol=0 (off); fancontrol=1 (on)

       P3OUT = 0x00;   //initialize output port to ground
       P2OUT = 0x00;
      
       __delay_cycles(100000);
       lcd_init();      //get the lcd booted up
      
      
      //RX Parameters
      UCA0CTL1 |= UCSSEL_2;                     // SMCLK
      UCA0BR0 = 104;                            // 1MHz 9600
      UCA0BR1 = 0;                              // 1MHz 9600
      UCA0MCTL = UCBRS0;                        // Modulation UCBRSx = 1
      UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
      IE2 |= UCA0RXIE;                          // Enable USCI_A0 RX interrupt
     
      while (1) {
         __bis_SR_register(CPUOFF + GIE);       // Enter LPM0 w/ interrupt
         displayTemp();
         //inputTemp();
      }
    }

    // Receive RXed character
    #pragma vector=USCIAB0RX_VECTOR
    __interrupt void USCI0RX_ISR(void)
    {
     
         apiframe[j] = UCA0RXBUF;
         if ((j == 0 && apiframe[j] == 0x7E) || j > 0) {
             data[j] = apiframe[j];
         }
         if (j == 11) { 
            dh = data[j];
         }
         if (j == 12) { 
            dl = data[j];
                 //dataReady = 1;
         }
         if (j > sizeof apiframe - 1) {  
              j = 0;
              __bic_SR_register_on_exit(CPUOFF);        // Return to active mode
         }
         j++;  
    }

  • Suzanne,

    I give you an A+ on your homework assignment.

    Jim

     

**Attention** This is a public forum