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.

MSP430FR2355: PROBLEM WITH SPI COMMUNICATION

Part Number: MSP430FR2355

Hello, 

I would like to cummunicate between two MSP430FR2355 with a SPI communication. I have one master microcontroller, and five slave microcontrollers (all microcontroller are MSP430FR2355).

The Spi configuration of my master is in 3wire and I use 5 IO for Chip select the right slave. All the slave are in 4 wire configuration.

My problem is the following:

I can't send and receive any data when I use the mode_2 of slave spi (Chip Select Active low). But when I use the mode_1 (Chip Select Active High) I can send and receive data. My IO connect to the STE pin hold High at 1.6V, even I configure the IO low.

Is STE connected to IO possible with this type of microcontroller?

//SLAVE SPI

#include <msp430.h>
#include "gpio.h"
int main(void)
{
    WDTCTL = WDTPW|WDTHOLD;                   // Stop watchdog timer


    //Configuration SPI pins on Hardawre
    P4SEL0 |= BIT0 | BIT1 | BIT2 | BIT3;             // set 4-SPI pin as second function

    GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN3); //indication alimentation
    GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN3);

    GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN4); //indication reception
    GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN4);

    UCA1CTLW0 |= UCSWRST;                     // **Put state machine in reset**
    UCA1CTLW0 |= UCSYNC|UCMSB|UCMODE_1|UCSTEM;         // 3-pin, 8-bit SPI slave
                                              // Clock polarity high, MSB
    UCA1CTLW0 |= UCSSEL__SMCLK;                // ACLK
    UCA1BR0 = 0x02;                           // BRCLK = ACLK/2
    UCA1BR1 = 0;                              //

    UCA1CTLW0 &= ~UCSWRST;                    // **Initialize USCI state machine**

    PM5CTL0 &= ~LOCKLPM5;                     // Disable the GPIO power-on default high-impedance mode
                                              // to activate previously configured port settings
    UCA1IE |= UCRXIE;                     // Enable TX interrupt
    __bis_SR_register(GIE);       // Enter LPM0, enable interrupts
}

#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
{   while (!(UCB1IFG&UCTXIFG));               // USCI_B1 TX buffer ready?
    UCA1TXBUF = UCA1RXBUF;                    // Echo received data
    GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN4);
}

//MASTER SPI

#include <msp430.h> 
#include "gpio.h"

/**
 * main.c
 */

//3.6 CS
//UCA1 SPI


unsigned char TXData;
unsigned char RXData;                            // Holds TX data

int main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
	
    P4SEL0 |= BIT3 | BIT2 | BIT1;             // set 3-SPI pin as second function

    GPIO_setAsOutputPin(GPIO_PORT_P3, GPIO_PIN6);


    GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN3);

    UCA1CTLW0 |= UCSWRST;                     // **Put state machine in reset**

    UCA1CTLW0 |= UCMST|UCSYNC|UCMSB;          // 3-pin, 8-bit SPI master
                                              // Clock polarity high, MSB
    UCA1CTLW0 |= UCSSEL__SMCLK;                // Select SMCLK

    UCA1BR0 = 0x02;                           // BRCLK = SMCLK/2
    UCA1BR1 = 0;                              //

    UCA1CTLW0 &= ~UCSWRST;                    // **Initialize USCI state machine**

    TXData = 0x01;                            // Holds TX data

    PM5CTL0 &= ~LOCKLPM5;

    GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN3);
    //GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN6);
    while(1)
    {
        UCA1IE |= UCTXIE;                     // Enable TX interrupt
        __bis_SR_register(GIE);   // enable global interrupts, enter LPM0
        __no_operation();                     // For debug,Remain in LPM0
        __delay_cycles(10000);                 // Delay before next transmission
        TXData++;                             // Increment transmit data
    }
}



#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
{
    switch(__even_in_range(UCA1IV,USCI_SPI_UCTXIFG))
    {
        case USCI_NONE: break;                // Vector 0 - no interrupt
        case USCI_SPI_UCRXIFG:
              RXData = UCA1RXBUF;
              UCA1IFG &= ~UCRXIFG;
              break;
        case USCI_SPI_UCTXIFG:
            GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN6);
              UCA1TXBUF = TXData;             // Transmit characters
            GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN6);
              UCA1IE &= ~UCTXIE;
              break;
        default: break;
    }
}

  • Your drawing seems to say you have the slave STE (P4.0) tied to 3.6V (high), which I suspect isn't your intent. Your code seems to think you've tied (slave) STE to (master) P3.6. 

    How is this actually wired?

    [Edit: Seeing this in bigger print, I suspect your drawing meant to say P3.6, not 3.6V.

    Looking further: Your master seems to be assuming STE is active low, but the slave assumes active high (UCMODE=1). 

    Also: If you're using the Launchpad, be sure to remove the RXD/TXD jumpers from J101. These affect SIMO/SOMI, not STE, but you still should do it.]

    -------------

    Unsolicited:

    > GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN6);
    > UCA1TXBUF = TXData; // Transmit characters
    > GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN6);

    This probably de-asserts STE before the byte has shifted out, which will freeze the slave SPI (even mid-byte, as I recall). You should hold off until the byte completes, with something resembling:

    > while (UCA1STATW & UCBUSY) /*EMPTY*/;  // Wait for byte to be shifted out

    -------------

    > { while (!(UCB1IFG&UCTXIFG)); // USCI_B1 TX buffer ready?

    I think this works by accident. It should probably be

    > { while (!(UCA1IFG&UCTXIFG)); // USCI_A1 TX buffer ready?

  • Thanks for your answer.

    I modify my program, and I can send and receive correctly in mode_ 1(STE HIGH for slave).

    But I can't send and receive in mode_2 (STE LOW for slave), yet I put my IO in low output. I think the bus between STE(slave) and 3.6 stay high (I measure 1.3V when I put the output of my IO(3.6) only at low).

    Why my bus is always in High ? STE in Slave put a voltage in output? I join my new code.

    #include <msp430.h>
    #include "gpio.h"
    
    void main(void)
    {
        WDTCTL = WDTPW|WDTHOLD;                   // Stop watchdog timer
    
    
        //Configuration SPI pins on Hardawre
        P4SEL0 |= BIT0 | BIT1 | BIT2 | BIT3;             // set 4-SPI pin as second function
    
        GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN3); //indication alimentation
        GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN3);
    
        GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN4); //indication reception
        GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN4);
    
        UCA1CTLW0 |= UCSWRST;                     // **Put state machine in reset**
        UCA1CTLW0 |= UCSYNC|UCMSB|UCMODE_1;         // 3-pin, 8-bit SPI slave
                                                  // Clock polarity high, MSB
        UCA1CTLW0 |= UCSSEL__SMCLK;
        UCA1BR0 = 0x02;
        UCA1BR1 = 0;                              //
    
        UCA1CTLW0 &= ~UCSWRST;                    // **Initialize USCI state machine**
    
        PM5CTL0 &= ~LOCKLPM5;                     // Disable the GPIO power-on default high-impedance mode
                                                  // to activate previously configured port settings
        UCA1IE |= UCRXIE;                     // Enable TX interrupt
        __bis_SR_register(GIE);       // Enter LPM0, enable interrupts
    }
    
    #pragma vector=USCI_A1_VECTOR
    __interrupt void USCI_A1_ISR(void)
    {   while (!(UCA1IFG&UCTXIFG));               // USCI_A1 TX buffer ready?  //erreur 15/04/24 B1->A1
        UCA1TXBUF = UCA1RXBUF;                    // Echo received data
        GPIO_toggleOutputOnPin(GPIO_PORT_P2, GPIO_PIN4);
    }
    

    #include <msp430.h> 
    #include "gpio.h"
    
    /**
     * main.c
     */
    
    //3.6 CS
    //UCA1 SPI
    
    
    unsigned char TXData;
    unsigned char RXData;                            // Holds TX data
    
    int main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    	
        P4SEL0 |= BIT3 | BIT2 | BIT1;             // set 3-SPI pin as second function
    
        GPIO_setAsOutputPin(GPIO_PORT_P3, GPIO_PIN6);
        GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN6);
    
        GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN3);
    
        UCA1CTLW0 |= UCSWRST;                     // **Put state machine in reset**
    
        UCA1CTLW0 |= UCMST|UCSYNC|UCMSB;          // 3-pin, 8-bit SPI master
                                                  // Clock polarity high, MSB
        UCA1CTLW0 |= UCSSEL__SMCLK;                // Select SMCLK
    
        UCA1BR0 = 0x02;                           // BRCLK = SMCLK/2
        UCA1BR1 = 0;                              //
    
        UCA1CTLW0 &= ~UCSWRST;                    // **Initialize USCI state machine**
    
        TXData = 0x01;                            // Holds TX data
    
        PM5CTL0 &= ~LOCKLPM5;
    
        GPIO_setOutputHighOnPin(GPIO_PORT_P2, GPIO_PIN3);
    
        while(1)
        {
             UCA1IE |= UCTXIE | UCRXIE ;                     // Enable TX interrupt
            __bis_SR_register(GIE);   // enable global interrupts, enter LPM0
            //__no_operation();                     // For debug,Remain in LPM0
            __delay_cycles(10000);                 // Delay before next transmission
            TXData++;                             // Increment transmit data
        }
    }
    
    
    
    #pragma vector=USCI_A1_VECTOR
    __interrupt void USCI_A1_ISR(void)
    {
        switch(__even_in_range(UCA1IV,USCI_SPI_UCTXIFG))
        {
            case USCI_NONE: break;                // Vector 0 - no interrupt
            case USCI_SPI_UCRXIFG:
                  RXData = UCA1RXBUF;
                  UCA1IE &= ~UCRXIE;
                  break;
            case USCI_SPI_UCTXIFG:
               // GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN6);
                UCA1TXBUF = TXData;                    // Transmit characters
                while (UCA1STATW & UCBUSY) ;           /*EMPTY*/
               // GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN6);
                UCA1IE &= ~UCTXIE;
                  break;
            default: break;
        }
    }
    

  • Yes, it does sound like a bus conflict (some other agent driving the wire high), but I don't see how that would happen, based on what you've posted. 

    What platform are you using? Are these Launchpads?

**Attention** This is a public forum