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.

LP-MSP430FR2476: SPI transmit and receive interrupts

Part Number: LP-MSP430FR2476


I have the MSP430 SPI setup to talk to a slave peripheral. The wakeup sequence has a total of 9 transactions. There is a return byte expected after transaction 5. No other transactions returns a byte. I am having trouble with SPI receive. It seems to take on a value of 0xff with every byte and this triggers the receive interrupt. I am not able to complete the sequence successfully because I am not getting back the needed byte. The slaves work fine with the evaluation GUI. I appreciate pointers on what can be changed here.

Going to experiment will a polled approach.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include <driverlib.h>
#include <msp430.h> 
#include "clock~.h"                 // Clock configurations


static uint8_t TXData = 0;           //transaction count
static uint8_t RXData = 0;           //SPI receive byte
static uint8_t waitForReceive = 0;


typedef struct {
    uint8_t     Len;
    uint8_t    Data[5];
} spi_MaximTrans_t;

static spi_MaximTrans_t DCInit_transactions[15];


uint8_t SPI_TX_index = 0;            //byte count in transaction

/**
 *  Initialize system clocks
 */
static void init_clock(void) {
    // Configure one FRAM waitstate as required by the device datasheet for MCLK
    // operation beyond 8MHz _before_ configuring the clock system.
    FRAMCtl_configureWaitStateControl(FRAMCTL_ACCESS_TIME_CYCLES_1);

    //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);

    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);

    //Set MCLK = REFO
    CS_initClockSignal(CS_MCLK,   CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);
    //Set SMCLK = DCO
    CS_initClockSignal(CS_SMCLK,  CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1);

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

/**
 *  Initialize all of the IO pins per their configuration
 */
static void init_gpio(void) {
    // Set all GPIO pins to output low to prevent floating input and reduce power consumption
    GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN_ALL8);
    GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN_ALL8);
    GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN_ALL8);
    GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN_ALL8);
    GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN_ALL8);
    GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);





    GPIO_setAsOutputPin(   GPIO_PORT_P1, GPIO_PIN_ALL8);
    GPIO_setAsOutputPin(   GPIO_PORT_P2, GPIO_PIN_ALL8);
    GPIO_setAsOutputPin(   GPIO_PORT_P3, GPIO_PIN_ALL8);
    GPIO_setAsOutputPin(   GPIO_PORT_P4, GPIO_PIN_ALL8);
    GPIO_setAsOutputPin(   GPIO_PORT_P5, GPIO_PIN_ALL8);
    GPIO_setAsOutputPin(   GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);



}

/*
 * Initialize the SPI peripheral on EUSCI A1
 */
void init_spi_peripheral()
{
    //Initialize Master
        EUSCI_A_SPI_initMasterParam param = {0};
        param.selectClockSource = EUSCI_A_SPI_CLOCKSOURCE_SMCLK;
        param.clockSourceFrequency = CS_getSMCLK();
        param.desiredSpiClock = 1000000;
        param.msbFirst = UCMSB;
        param.clockPhase = 0;
        param.clockPolarity = EUSCI_A_SPI_CLOCKPOLARITY_INACTIVITY_LOW;
        param.spiMode = EUSCI_A_SPI_3PIN;
        EUSCI_A_SPI_initMaster(EUSCI_A1_BASE, &param);

        EUSCI_A_SPI_enable(EUSCI_A1_BASE);

        // Enable the TX and RX interrupts for the SPI bus.
        EUSCI_A_SPI_enableInterrupt(EUSCI_A1_BASE, EUSCI_A_SPI_TRANSMIT_INTERRUPT);
        EUSCI_A_SPI_enableInterrupt(EUSCI_A1_BASE, EUSCI_A_SPI_RECEIVE_INTERRUPT);
}


void SetUpTransactions(void){
    //Enable keep alive mode
    DCInit_transactions[0].Len = 2;
    DCInit_transactions[0].Data[0] = 0x10;
    DCInit_transactions[0].Data[1] = 0x5;       //No Receive

    //Enable Rx Interrupt flags
    DCInit_transactions[1].Len = 2;
    DCInit_transactions[1].Data[0] = 0x4;
    DCInit_transactions[1].Data[1] = 0x88;      //No Receive

    //Clear receive buffer
    DCInit_transactions[2].Len = 1;
    DCInit_transactions[2].Data[0] = 0xe0;      //No Receive

    //Wakeup UART slave devices
    DCInit_transactions[3].Len = 2;
    DCInit_transactions[3].Data[0] = 0xe0;
    DCInit_transactions[3].Data[1] = 0x30;      //No Receive

    //Wait for all UART slave devices to wake up
    DCInit_transactions[4].Len = 1;
    DCInit_transactions[4].Data[0] = 0x01;      //Receive of 0x21 expected

    //End of UART slave device wake-up period
    DCInit_transactions[5].Len = 2;
    DCInit_transactions[5].Data[0] = 0x0e;
    DCInit_transactions[5].Data[1] = 0x10;      //No Receive

    //Wait for null message to be received
    DCInit_transactions[6].Len = 1;
    DCInit_transactions[6].Data[0] = 0x01;      //No Receive

    //Clear transmit buffer
    DCInit_transactions[7].Len = 1;
    DCInit_transactions[7].Data[0] = 0x20;      //No Receive

    //Clear receive buffer
    DCInit_transactions[8].Len = 1;
    DCInit_transactions[8].Data[0] = 0xe0;      //No Receive

}


/**
 * main.c
 */
int main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
	

    init_clock();
    init_gpio();                                    // Set up IO pins

    GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);

    // Configure SPI Pins for UCA1CLK, UCA1TXD/UCA1SIMO and UCA1RXD/UCA1SOMI
    /*
    * Select Port 2
    * Set Pin 4, Pin 5 and Pin 6 to input Secondary Module Function
    */
    GPIO_setAsPeripheralModuleFunctionInputPin(
        GPIO_PORT_P2,
        GPIO_PIN4 + GPIO_PIN5 + GPIO_PIN6,
        GPIO_PRIMARY_MODULE_FUNCTION
    );

    // Set P1.0 to output direction

    GPIO_setAsOutputPin (GPIO_PORT_P1, GPIO_PIN0);
    GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P4, GPIO_PIN2);
    GPIO_enableInterrupt (GPIO_PORT_P4, GPIO_PIN2);
    GPIO_selectInterruptEdge (GPIO_PORT_P4, GPIO_PIN2, GPIO_HIGH_TO_LOW_TRANSITION);
    GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2);

    PMM_unlockLPM5();

    SetUpTransactions();
    TXData = 0x0;                             // Holds transaction number


    // Setup peripheral(s) now that gpio and clocks are setup
    init_spi_peripheral();                      // Init Maxim spi peripheral
    //Wait for slave to initialize
        __delay_cycles(100);

    GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN1);        //Maxim chip select low
    UCA1IFG |= UCTXIFG;


    __bis_SR_register(LPM0_bits + GIE);      // CPU off, enable interrupts
    __no_operation();                       // Remain in LPM0


	return 0;
}

//******************************************************************************
//
//This is the PORT2_VECTOR interrupt vector service routine
//
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=PORT4_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(PORT2_VECTOR)))
#endif
void P4_ISR (void)
{
 //   GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);
    GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2);
    // Toggle P1.0 output
    GPIO_toggleOutputOnPin (GPIO_PORT_P1, GPIO_PIN0);

    GPIO_disableInterrupt (GPIO_PORT_P4, GPIO_PIN2);
}


/****************************************************************************
 * EUSCI_A1_isr()
 *
 * This interrupt is used for SPI interrupts (UCA1).
 ****************************************************************************/
#pragma vector = EUSCI_A1_VECTOR
__interrupt void EUSCI_A1_isr(void)
{
    // SPI TX interrupt?
    if (UCA1IFG & UCTXIFG)
    {
        while (UCA1STATW & UCBUSY);
        EUSCI_A_SPI_transmitData(EUSCI_A1_BASE, DCInit_transactions[TXData].Data[SPI_TX_index]);
        SPI_TX_index++;

        if (SPI_TX_index == DCInit_transactions[TXData].Len){
                   SPI_TX_index = 0;
                   if (!waitForReceive)
                       TXData = TXData+1;
                   if (TXData == 5){
                       TXData = 4;
                       waitForReceive = 1;
                   }

                   if (TXData == 9) {
                      while (UCA1STATW & UCBUSY);     //wait for the last byte to transmit
                         EUSCI_A_SPI_disableInterrupt(EUSCI_A1_BASE, EUSCI_A_SPI_TRANSMIT_INTERRUPT);
                         EUSCI_A_SPI_disableInterrupt(EUSCI_A1_BASE, EUSCI_A_SPI_RECEIVE_INTERRUPT);
                   }
        }
        /* Put a new byte to send into the TX buffer.
         * This prevents us from stuffing an extra byte.
         *****/

            /* Disable the TX interrupt.  Since the last byte of the message
             * has been sent, disable the TX interrupt.  If this is not done,
             * the ISR will be repeatedly invoked between the time that the
             * time that the UCA1TXBUF is empty and the time that the receive
             * byte is available in UCA1RXBUF.
             *****/
     }

    if (UCA1IFG & UCRXIFG)
    {
        RXData = EUSCI_A_SPI_receiveData(EUSCI_A1_BASE);
        if (waitForReceive && (RXData == 0x21)){
            waitForReceive = 0;
            TXData = 5;
        }

    }

}


  • With a fast SPI and short transactions, I recommend not using interrupts at all, since they complicate your design and actually slow your system down. This recommendation gets stronger for the case where you're mixing Tx and Rx, since (a) it's difficult to match up the Tx with the Rx bytes and (b) Rx overruns are almost inevitable.

    Over the years, I've gotten much mileage out of the spix() function over here:

    https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/758000/msp430fr5729-problems-with-implementing-mcp23s08-8-bit-port-expander-on-msp430fr5729/2800722#2800722

    It's deliberately simple, so you always know which byte you're working with, and with a fast SPI the spin-loops don't spin very long.

  • That wait on TXIFG in spix() is a waste of time because it will always be set. After putting a byte into TXBUF spix() then waits for a byte to appear in RXBUF. When that happens, not only is the transmit shift register empty but TXBUF has long been empty.

    The problem with the interrupt is that there is a byte received with every byte transmitted. Worse is that the timing is skewed.

    waitForReceive is set just after data is transferred to TXBUF and the previous byte is in the transmit shift register. Which means that when the receive interrupt is triggered, it will be for that slot. Not for the data waiting in TXBUF.

  • #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    
    #include <driverlib.h>
    #include <msp430.h> 
    #include "clock~.h"                 // Clock configurations
    
    
    static uint8_t TXData = 0;           //transaction count
    static uint8_t RXData = 0;           //SPI receive byte
    
    
    typedef struct {
        uint8_t     Len;
        uint8_t    Data[5];
    } spi_MaximTrans_t;
    
    static spi_MaximTrans_t DCInit_transactions[15];
    
    
    uint8_t SPI_TX_index = 0;            //byte count in transaction
    
    /**
     *  Initialize system clocks
     */
    static void init_clock(void) {
        // Configure one FRAM waitstate as required by the device datasheet for MCLK
        // operation beyond 8MHz _before_ configuring the clock system.
        FRAMCtl_configureWaitStateControl(FRAMCTL_ACCESS_TIME_CYCLES_1);
    
        //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);
    
        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);
    
        //Set MCLK = REFO
        CS_initClockSignal(CS_MCLK,   CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);
        //Set SMCLK = DCO
        CS_initClockSignal(CS_SMCLK,  CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1);
    
        //Clear all OSC fault flag
        CS_clearAllOscFlagsWithTimeout(1000);
    }
    
    /**
     *  Initialize all of the IO pins per their configuration
     */
    static void init_gpio(void) {
        // Set all GPIO pins to output low to prevent floating input and reduce power consumption
        GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);
    
        GPIO_setAsOutputPin(   GPIO_PORT_P1, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P2, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P3, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P4, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P5, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);
    
    }
    
    /*
     * Initialize the SPI peripheral on EUSCI A1
     */
    void init_spi_peripheral()
    {
        //Initialize Master
            EUSCI_A_SPI_initMasterParam param = {0};
            param.selectClockSource = EUSCI_A_SPI_CLOCKSOURCE_SMCLK;
            param.clockSourceFrequency = CS_getSMCLK();
            param.desiredSpiClock = 1000000;
            param.msbFirst = UCMSB;
            param.clockPhase = 0;
            param.clockPolarity = EUSCI_A_SPI_CLOCKPOLARITY_INACTIVITY_LOW;
            param.spiMode = EUSCI_A_SPI_3PIN;
            EUSCI_A_SPI_initMaster(EUSCI_A1_BASE, &param);
    
            EUSCI_A_SPI_enable(EUSCI_A1_BASE);
    
    }
    
    
    void SetUpTransactions(void){
        //Enable keep alive mode
        DCInit_transactions[0].Len = 2;
        DCInit_transactions[0].Data[0] = 0x10;
        DCInit_transactions[0].Data[1] = 0x5;       //No Receive
    
        //Enable Rx Interrupt flags
        DCInit_transactions[1].Len = 2;
        DCInit_transactions[1].Data[0] = 0x4;
        DCInit_transactions[1].Data[1] = 0x88;      //No Receive
    
        //Clear receive buffer
        DCInit_transactions[2].Len = 1;
        DCInit_transactions[2].Data[0] = 0xe0;      //No Receive
    
        //Wakeup UART slave devices
        DCInit_transactions[3].Len = 2;
        DCInit_transactions[3].Data[0] = 0xe0;
        DCInit_transactions[3].Data[1] = 0x30;      //No Receive
    
        //Wait for all UART slave devices to wake up
        DCInit_transactions[4].Len = 1;
        DCInit_transactions[4].Data[0] = 0x01;      //Receive of 0x21 expected
    
        //End of UART slave device wake-up period
        DCInit_transactions[5].Len = 2;
        DCInit_transactions[5].Data[0] = 0x0e;
        DCInit_transactions[5].Data[1] = 0x10;      //No Receive
    
        //Wait for null message to be received
        DCInit_transactions[6].Len = 1;
        DCInit_transactions[6].Data[0] = 0x01;      //No Receive
    
        //Clear transmit buffer
        DCInit_transactions[7].Len = 1;
        DCInit_transactions[7].Data[0] = 0x20;      //No Receive
    
        //Clear receive buffer
        DCInit_transactions[8].Len = 1;
        DCInit_transactions[8].Data[0] = 0xe0;      //No Receive
    
    }
    
    
    /**
     * main.c
     */
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    
    
        init_clock();
        init_gpio();                                    // Set up IO pins
    
        GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);
    
        // Configure SPI Pins for UCA1CLK, UCA1TXD/UCA1SIMO and UCA1RXD/UCA1SOMI
        /*
        * Select Port 2
        * Set Pin 4, Pin 5 and Pin 6 to input Secondary Module Function
        */
        GPIO_setAsPeripheralModuleFunctionInputPin(
            GPIO_PORT_P2,
            GPIO_PIN4 + GPIO_PIN5 + GPIO_PIN6,
            GPIO_PRIMARY_MODULE_FUNCTION
        );
    
        // Set P1.0 to output direction
    
        GPIO_setAsOutputPin (GPIO_PORT_P1, GPIO_PIN0);
        GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P4, GPIO_PIN2);
        GPIO_enableInterrupt (GPIO_PORT_P4, GPIO_PIN2);
        GPIO_selectInterruptEdge (GPIO_PORT_P4, GPIO_PIN2, GPIO_HIGH_TO_LOW_TRANSITION);
        GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2);
    
        PMM_unlockLPM5();
    
    
        SetUpTransactions();
        TXData = 0x0;                             // Holds transaction number
    
    
        // Setup peripheral(s) now that gpio and clocks are setup
        init_spi_peripheral();                      // Init Maxim spi peripheral
        //Wait for slave to initialize
    
    
        GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN1);        //Maxim chip select low
    
        while (TXData < 10){
            for(SPI_TX_index = 0; SPI_TX_index < DCInit_transactions[TXData].Len; SPI_TX_index++){
                EUSCI_A_SPI_transmitData(EUSCI_A1_BASE, DCInit_transactions[TXData].Data[SPI_TX_index]);
            }
            __delay_cycles(100);
            TXData = TXData+1;
            if (TXData == 5){
                while(!(UCA1IFG & UCRXIFG));
                    RXData = EUSCI_A_SPI_receiveData(EUSCI_A1_BASE);
                    if (RXData != 0x21)
                        TXData = 4;
            }
        }
    
    
    }
    
    //******************************************************************************
    //
    //This is the PORT2_VECTOR interrupt vector service routine
    //
    //******************************************************************************
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=PORT4_VECTOR
    __interrupt
    #elif defined(__GNUC__)
    __attribute__((interrupt(PORT2_VECTOR)))
    #endif
    void P4_ISR (void)
    {
     //   GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);
        GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2);
        // Toggle P1.0 output
        GPIO_toggleOutputOnPin (GPIO_PORT_P1, GPIO_PIN0);
    
        GPIO_disableInterrupt (GPIO_PORT_P4, GPIO_PIN2);
    }
    
    
    

    Here is my polling code. The SPI transmits are happening, but the expected receive data is not coming. The SPI is repeatedly sending transaction 5. I will look more closely at the slave datasheet to see if any other register needs setting up. Things work fine with the eval GUI. If you note anything amiss with the polling code, please let me know. Maybe its the new scope, the triggers are not showing up every time. 

    Thanks

  • It appears that you are transmitting a sequence of bytes, waiting briefly, and then looking for a received byte. This is a race and really bad practice even if it works.

    You wait 100 MCLKs. If what you want is final received data byte that will happen about 16 SPI clocks after you send a byte. (Assuming that the shift register is busy and the data just put in TXBUF is waiting. The SPI clock appears to be 1MHz and while I can't tell what MCLK is, it appears to greater than 8MHz.

    Even at 8Mhz that would mean 8*16  or 128 MCLKs before the transmit (and receive) was complete. Which means that you are getting the second to last received byte.

  • Thank you for your reply. The SPI clock source frequency reads 15990784, approx 16 MHz. Can you refer me to where I can find that receive data is 16 SPI clocks after the send byte? 

    I re-structured the SPI transactions below. I am still not seeing a receive byte.

      while (TXData < 10){
            for(SPI_TX_index = 0; SPI_TX_index < DCInit_transactions[TXData].Len; SPI_TX_index++){
                UCA1TXBUF = DCInit_transactions[TXData].Data[SPI_TX_index];
            }
    
            if (UCA1IFG & UCRXIFG)
                RXData = UCA1RXBUF;
            if (((TXData == 4) && (RXData == 0x21)) || (TXData != 4)){
                TXData = TXData+1;
            }
            else
                TXData = 4;
    
            __delay_cycles(100);
        }

  • " param.desiredSpiClock = 1000000;"

    I get 16 SPI clocks from the way the hardware is designed. TXIFG is set when data is transferred from TXBUF to the transmit shift register. Assuming a minimal delay before putting new data in TXBUF that means there are 8 bits in the transmit shift register plus the 8 bits in TXBUF to send before the SPI hardware completes operation. UCBUSY will be cleared once the SPI hardware goes idle.

    So your latest bit of code will read the byte received too soon. RXIFG will be already be set. Then set again when the  data in the shift register is completely sent and then again when the data in TXBUF is shifted out.

    You really should be reading all data in RXBUF (see spix() previously discussed) even if you just ignore it. This bit of sending a bunch of data and trying to look at just one of the received bytes in RXBUF will never work well.

  •     while (TXData < 10){
            for(SPI_TX_index = 0; SPI_TX_index < DCInit_transactions[TXData].Len; SPI_TX_index++){
                UCA1TXBUF = DCInit_transactions[TXData].Data[SPI_TX_index];
                while (UCA1STATW & UCBUSY){
                   RXData = UCA1RXBUF;
                }
            }
    
            if (((TXData == 4) && (RXData == 0x21)) || (TXData != 4)){
                TXData = TXData+1;
            }
            else
                TXData = 4;
    
            __delay_cycles(100);
        }
    

    I am not clear on the spix() discussion. Here is what I tried next. No difference yet in the result.

  •         for(SPI_TX_index = 0; SPI_TX_index < DCInit_transactions[TXData].Len; SPI_TX_index++){
                UCA1TXBUF = DCInit_transactions[TXData].Data[SPI_TX_index];
                while (!(UCA1IFG & UCRXIFG))
                  ;
                RXData = UCA1RXBUF;
            }

  • That makes sense, thank you for posting it. I am not seeing any changes in RXData still. I will try the scope next. Since I changes to polling mode, the scope if not probing the pins properly. If I recalibrate the probe and then try, I see a display. Its a $500 scope, not sure if that has anything to do with it.

    I am opening a support ticket with Maxim about the handshaking. If I run into any SPI issues on the MSP430 end, I will open a new thread.

**Attention** This is a public forum