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.

MSP430F2274: SPI Communication Acting Unpredictably Between Master and Slave

Part Number: MSP430F2274


The simple program I am trying to run is to have the slave's LEDs light up when the button on the master is pressed, and then transmit data the slave received to illuminate the master's LEDs. My code for both the master and slave are shown, beginning with the master.

#include <msp430.h>
#include <stdint.h>
#define SLAVE_CS_OUT P3OUT #define SLAVE_CS_DIR P3DIR #define SLAVE_CS_PIN BIT0 #define SLAVE_RST_OUT P4OUT #define SLAVE_RST_DIR P4DIR #define SLAVE_RST_PIN BIT6 #define BUTTON_DIR P1DIR #define BUTTON_OUT P1OUT #define BUTTON_REN P1REN #define BUTTON_PIN BIT2 #define BUTTON_IES P1IES #define BUTTON_IE P1IE #define BUTTON_IFG P1IFG #define BUTTON_VECTOR PORT1_VECTOR #define BUTTON_LED_OUT P1OUT #define BUTTON_LED_DIR P1DIR #define BUTTON_LED_PIN BIT0 #define COMMS_LED_OUT P1OUT #define COMMS_LED_DIR P1DIR #define COMMS_LED_PIN BIT1 void SendUCB0Data(uint8_t val) { while (!(IFG2 & UCB0TXIFG)); // USCI_A0 TX buffer ready? UCB0TXBUF = val; } void configClocks() { DCOCTL |= DCO1 + DCO0; // DCOCTL = 0x60 BCSCTL1 |= XT2OFF + DIVA_3 + RSEL2 + RSEL1 + RSEL0; // BCSCTL1 = 0xB7 BCSCTL2 |= SELM_3 + SELS; // BCSCTL2 = 0xC8 BCSCTL3 |= XT2S_3; // BCSCTL3 = 0xC0 } void initGPIO() { //LEDs COMMS_LED_DIR |= COMMS_LED_PIN; COMMS_LED_OUT &= ~COMMS_LED_PIN; BUTTON_LED_DIR |= BUTTON_LED_PIN; BUTTON_LED_OUT &= ~BUTTON_LED_PIN; //SPI Pins P3SEL = BIT3 | BIT2 | BIT1; SLAVE_RST_DIR |= SLAVE_RST_PIN; SLAVE_RST_OUT |= SLAVE_RST_PIN; SLAVE_CS_DIR |= SLAVE_CS_PIN; SLAVE_CS_OUT |= SLAVE_CS_PIN; //Button to initiate transfer BUTTON_DIR &= ~(BUTTON_PIN); // button input BUTTON_OUT |= BUTTON_PIN; // button pull up BUTTON_REN |= BUTTON_PIN; // button pull up/down resistor enable BUTTON_IES |= BUTTON_PIN; // button Hi/lo edge BUTTON_IE |= BUTTON_PIN; // button interrupt enabled BUTTON_IFG &= ~BUTTON_PIN; // button IFG cleared } void initSPI() { UCB0CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC; UCB0CTL1 |= UCSSEL_1; // ACLK UCB0BR0 |= 0x03; // /32 UCB0BR1 = 0; // UCA0MCTL = 0; // No modulation must be cleared for SPI UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** IE2 |= UCB0RXIE; // Enable USCI0 RX interrupt } int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer configClocks(); initGPIO(); initSPI(); SLAVE_RST_OUT &= ~SLAVE_RST_PIN; // Now with SPI signals initialized, __delay_cycles(1000); SLAVE_RST_OUT |= SLAVE_RST_PIN; // reset slave __delay_cycles(1000); // Wait for slave to initialize while(1) __bis_SR_register(LPM3_bits + GIE); } #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=USCIAB0RX_VECTOR __interrupt void USCIB0RX_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCIA0RX_ISR (void) #else #error Compiler not supported! #endif { if(IFG2 & UCB0RXIFG) { COMMS_LED_OUT = UCB0RXBUF; __no_operation(); } //IFG2 &= ~UCB0RXIFG; //BUTTON_IFG &= ~BUTTON_PIN; //__delay_cycles(1000); } #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=BUTTON_VECTOR __interrupt void Button_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(BUTTON_VECTOR))) Button_ISR (void) #else #error Compiler not supported! #endif { static volatile char send_byte; BUTTON_IFG &= ~BUTTON_PIN; // button IFG cleared if(send_byte == 0) { SendUCB0Data(0x01); send_byte = 1; } else if(send_byte == 1) { SendUCB0Data(0x02); send_byte = 2; } else if(send_byte == 2) { SendUCB0Data(0x03); send_byte = 3; } else if(send_byte == 3) { SendUCB0Data(0x00); send_byte = 0; } //Initiate __bic_SR_register_on_exit(LPM3_bits); // Exit LPM0 }

#include <msp430.h>
#include <stdint.h>

#define SLAVE_CS_IN     P3IN
#define SLAVE_CS_DIR    P3DIR
#define SLAVE_CS_PIN    BIT0

#define CLK_IN          P3IN
#define CLK_PIN         BIT3

#define LED_OUT         P1OUT
#define LED_DIR         P1DIR
#define RED_LED_PIN     BIT0
#define GREEN_LED_PIN   BIT1


void SendUCB0Data(uint8_t val)
{
    while (!(IFG2 & UCB0TXIFG));              // USCI_A0 TX buffer ready?
    UCB0TXBUF = val;
}


void configClocks()
{
    DCOCTL |= DCO1 + DCO0;                                  // DCOCTL = 0x60
    BCSCTL1 |= XT2OFF + DIVA_3 + RSEL2 + RSEL1 + RSEL0;     // BCSCTL1 = 0xB7
    BCSCTL2 |= SELM_3 + SELS;                               // BCSCTL2 = 0xC8
    BCSCTL3 |= XT2S_3;                                      // BCSCTL3 = 0xC0
}


void initGPIO()
{
  //SPI Pins
  P3SEL = BIT3 | BIT2 | BIT1;
  SLAVE_CS_DIR &= ~(SLAVE_CS_PIN);

  //LEDs
  LED_DIR |= RED_LED_PIN + GREEN_LED_PIN;
  LED_OUT &= ~RED_LED_PIN & ~GREEN_LED_PIN;
}

void initSPI()
{
  UCB0CTL1 = UCSWRST;                       // **Put state machine in reset**
  UCB0CTL0 |= UCCKPL + UCMSB + UCSYNC;      // 3-pin, 8-bit SPI Slave
  UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
  IE2 |= UCB0RXIE;                          // Enable USCI0 RX interrupt
}


int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop watchdog timer
  while (!(CLK_IN & CLK_PIN));              // If clock sig from mstr stays low,
                                            // it is not yet in SPI mode
  configClocks();
  initGPIO();
  initSPI();

  __bis_SR_register(LPM0_bits + GIE);       // Enter LPM4, enable interrupts
  __no_operation();
  return 0;
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCI0RX_ISR (void)
#else
#error Compiler not supported!
#endif
{
    //static volatile char send_byte;

    if(IFG2 & UCB0RXIFG)
    {
        LED_OUT = UCB0RXBUF;
        UCB0TXBUF = UCB0RXBUF;
    }
}

 When running this code, the master receives an RX interrupt, but will constantly stay in that ISR, or will trigger an interrupt for the pin corresponding to the button. The furthest it has gotten is illuminating one LED on the master, but then halting and never returning to the master's button ISR even when pressed. Commenting out the contents of the `if` statement within the master's RX ISR will cause the program to behave as predicted, where the slave's LEDs will illuminate or turn off during each button press on the master. Is there any reason as to why including the master's RX ISR causes the program to behave unpredictably? I can provide more information if needed. Thank you!

  • #define BUTTON_OUT P1OUT
    #define COMMS_LED_OUT P1OUT
    COMMS_LED_OUT = UCB0RXBUF;

    By writing the entire P1OUT, you're triggering the pin interrupt (repeatedly) by writing to P1OUT.2. Try:

    #define LED_PINS (BUTTON_LED_PIN|COMMS_LED_PIN)

    COMMS_LED_OUT = (COMMS_LED_OUT & ~LED_PINS) | (UCB0RXBUF & LED_PINS);

    [Edit: I typed "#-define" and it posted my half-written text. Go figure.]

**Attention** This is a public forum