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.

MSP430 Multiple SPI Transmission Processing

Other Parts Discussed in Thread: MSP430FR5739

I am using the MSP430 FR5739 to work as a 4-pin SPI slave device.  When I connect the device to an oscilloscope, I've noticed that the SPI clock has 24 clock cycles, rather than 8.  According to my understanding of SPI, I believe the SPI master is sending and receiving data to the MSP430 multiple times (without any pause in between).  Below is an example of the clock and the received data coming from the SPI master.

Where D0 is the SCLK, and D1 is the MOSI pin.  Below is my current RX Interrupt setup.


#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
{
    RXData = UCA0RXBUF;
    UCA0IFG &= ~UCRXIFG;
    __bic_SR_register_on_exit(CPUOFF);// Wake up to setup next TX
}

Any suggestions would be appreciated.

  • Hi dauletle,

    You didn't mention what isn't working the way you expected.  Are you worried about the master sending three bytes in a row without a pause?  That is OK by SPI standards, so if you (the slave) are also trying to send meaningful data during this exchange, you need to be ready with your data ahead of time so you know what you are sending and can keep the TXBUF stuffed.

    Or is it something else you need help with?

    Jeff

  • Jeff Tenney said:
    You didn't mention what isn't working the way you expected.

    My apologies for not being clear.  I believe that the code I am implementing is not optimized for the SPI master. I wanted my code to work in a way that it would receive all data coming from the SPI Master, and I'm not sure if the Receive interrupt responds quickly enough so that I can respond.  Should I have some logic inside the ISR so that it may respond quicker?

  • I've just answered my own question from earlier.  So it turns out that my RX interrupt is being initiated at the beginning of the transmission.  I've discovered this by allowing an IO pin to go high and low at the beginning and end of my ISR.  This is what occurred:

    As you can see, the interrupts are occurring before the data can be stored in the buffer, where I was under the impression that it would initiate after the receive buffer would be filled.  How would I change it so that the receive interrupt initiates once the buffer is filled?

  • Dauletle,

    Have you looked at the examples that are available for the MSP430FR5739? You can find it here:

    http://www.ti.com/general/docs/lit/getliterature.tsp?literatureNumber=slac491d&fileType=zip

    If you look at MSP430FR57xx_uscia0_spi_10.c , it shows setting up the SPI port in slave mode.  This would be a good reference for you to look at.

    Also, you can use the Grace plug in to setup a project for you that will setup the SPI port in RX mode. For more on Grace you can go here:

    http://www.ti.com/tool/grace

    -Jason

     

  • Jason Kriek said:
    Have you looked at the examples that are available for the MSP430FR5739?

    Along with the datasheet, I used the examples for the FR5739 as a resource to help me initially write my program.  It was useful, but my issue with my setup is that it isn't functioning the way I was hoping it would.  Specifically, I was under the impression that the RX Interrupt would initiate when the RX buffer was filled.  After looking at the oscilloscope, it looks like the ISR is being initiated when a single bit is intercepted into the RX buffer.

    Jason Kriek said:
    Also, you can use the Grace plug in to setup a project

    I did attempt that as well, except I rather look at the C source code than the Grace interface.  I was also unable to find any Grace examples for a SPI slave for the FR5739.

    However, I was able to find a Grace Example for a different series of the MSP-430 (MSP430F20x2), and I've noticed that they force a interrupt at the end of receiving data. The way they do this was by loading the counter.  In other microcontrollers, I've noticed that they do the same thing, so that an overflow interrupt would be initiated at the end of the receive cycle.  How would I initialize the SPI on the FR5739 so that the ISR would work at the end of the receive cycle?

  • Hi dauletle,

    In your latest scope picture (the one showing your ISR activity) it looks like the MSP430 was just waiting for the last rising clock edge.  In that case, you and the master don't have the same SPI clock settings.  You'll need to change your UCCKPL or UCCKPH setting to match the master.

    I have assumed that D1 (at the bottom) is the SS signal -- again I am talking about your latest scope picture.  Since your master's clock idles low, you need UCCKPL=0.  If D2 is MOSI, then the master is changing outputs on the falling edge, so you need UCCKPH=1.

    Jeff

  • Jeff Tenney said:
    I have assumed that D1 (at the bottom) is the SS signal

    Actually, D1 is the MISO pin, and D2 is the MOSI pin.  D3 is a pin I'm controlling to pin out where I am in the code.

    Jeff Tenney said:
    Since your master's clock idles low, you need UCCKPL=0.  If D2 is MOSI, then the master is changing outputs on the falling edge, so you need UCCKPH=1

    When I made this change, the code would not go into the ISR I have set up (I toggle a pin to indicate when I am in the ISR). What's strange is that even though I'm not in the ISR, the MISO pin keeps dropping while the SCK is running.  Any advice would help.  Meanwhile, I'll keep you posted if I find the solution.

  • In your most recently posted image (please look at it in this thread), I cannot believe that D1 is MISO.  I mean, it changes with no clock edge at all.  The eUSCI doesn't do that. However in your first image in this thread, D1 appears to be MISO.  D1 seems to have changed between scope pictures.

    But it doesn't matter, it appears that the eUSCI is out of sync with the master.  There can be a few causes for this.

    1. Wrong UCCKPL and UCCKPH settings.
    2. eUSCI brought out of reset while master was in the middle of a transfer.
    3. Master aborted a transfer.

    Problems 2 and 3 can be solved by your software resetting the eUSCI after a rising edge on SS.  Use an ISR.  Really The USCI itself should offer this capability via configuration, but it doesn't.  Even the new "enhanced" eUSCI (which you have) doesn't seem to offer this capability.  So you need to do it with an ISR.

    dauletle said:
    When I made this change, the code would not go into the ISR I have set up

    Very odd.  If the UCCKPL and UCCKPH settings are literally the only change, you should only see changes in the timing and RX byte values.  The ISR should still run during data exchanges.

    dauletle said:
    What's strange is that even though I'm not in the ISR, the MISO pin keeps dropping while the SCK is running.

    If you haven't put a new byte into the TXBUF when the eUSCI needs one, it will just use the last byte you put in there.  So it will just keep transmitting the same byte over and over again until you give it a new byte to transmit.

    Jeff

  • Jeff Tenney said:
    I cannot believe that D1 is MISO.  I mean, it changes with no clock edge at all.  The eUSCI doesn't do that.

    Oh, I stand corrected.  If the TXBUF held zero, and if MISO had a pull-up on it, then MISO would look exactly like D1 in that most recent scope shot.  It would actually look like a copy of SS.

    Jeff

  • Jeff Tenney said:

    But it doesn't matter, it appears that the eUSCI is out of sync with the master.  There can be a few causes for this.

    1. Wrong UCCKPL and UCCKPH settings.
    2. eUSCI brought out of reset while master was in the middle of a transfer.
    3. Master aborted a transfer.

    So I revised my program a little bit so that it may match the master SPI to the best of my knowledge.  Here is the way I am initializing the SPI again.

    void SPI_init(void)
    { // Configure SPI Pins
        // Pin 1.5 set for Serial Clock Out (UCA0CLK)
        // Pin 1.4 set for SS (Slave Select) (UCA0STE)
        P1SEL1 |= SPI_CLK + SPI_SS;

        // Configure SPI pins P2.0 and P2.1
        // Pin 2.0 set for Data Out (UCA0SIMO)
        // Pin 2.1 set for Data In (UCA0SOMI)
        P2SEL1 |= MOSI + MISO;
        UCA0CTLW0 |= UCSWRST; // **Put state machine in reset**

        
        

        // 4-pin, 8-bit SPI slave
        // Clock Phase; data captured on first UCLK
        // Clock polarity low, MSB
        // 4-Pin SPI, w/ UCxSTE Active Low
        UCA0CTLW0 |= UCSYNC + UCCKPH + UCMSB + UCMODE1;

        UCA0CTLW0 |= UCSSEL_2; // ACLK
        UCA0BR0 = 0x02; // /2
        UCA0BR1 = 0; //
        UCA0MCTLW = 0; // No modulation
        UCA0CTLW0 &= ~UCSWRST; // **Initialize USCI state machine**
        UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
    }

    Jeff Tenney said:
    Problems 2 and 3 can be solved by your software resetting the eUSCI after a rising edge on SS.

    I tried to reset the USI by calling the SPI initialize class in the SS interrupt. Here is the ISR for the SS pin when it goes high.

    // Port 1 interrupt service routine
    #pragma vector=PORT1_VECTOR
    __interrupt void Port_1(void)
    {
        // Reset the SPI
        SPI_init();
    }

    The issue is still occurring where the SPI ISR is not being initiated at the right times.  So from what I can see in the oscilloscope readings, I don't believe that my program is reading every transmission from the SPI master.  Not only that, I also believe that if it does initiate the SPI ISR, than it doesn't do it after the 8th clock pulse.  Below are some oscilloscope images, where D3 is the strobe pin to indicate when the SPI ISR is running, D2 is the MOSI, and D1 is the MISO.

    I lost the closeup of the last transmission in this oscilloscope reading. In this case, the ISR is being called at the sixth clock pulse

  • I think I found the biggest problem.  You are writing to the 16-bit register UCA0CTLW0, but you are writing values associated with the 8-bit registers UCA0CTL0 and UCA0CTL1.  As a result, you are never changing any bits in UCA0CTL0, and you are changing unintended bits in UCA0CTL1.

    Try writing to CTL1 and CTL0 separately and not writing to CTLW0.  (Note that you don't need to set the UCSSEL field or the baud-rate registers at all as an SPI slave.)

    Also the ISR for the rising edge on SS could be as simple as:

    UCA0CTL1 |= UCSWRST;
    UCA0CTL1 &= ~UCSWRST;
    UCA0IE |= UCRXIE;

    Jeff

  • Oops - I may have to eat my words twice in the same thread.  It appears that the .h file for the FR5739 defines the symbols for use with the 16-bit register CTLW0. 

    It would be good for you to double check the header file you are using to make sure they match these (from IAR):

    #define UCMSB               (0x2000u)    /* MSB first  0:LSB / 1:MSB */
    #define UC7BIT              (0x1000u)    /* Data Bits  0:8-bits / 1:7-bits */
    #define UCMODE1             (0x0400u)    /* USCI Mode 1 */
    #define UCMODE0             (0x0200u)    /* USCI Mode 0 */
    #define UCSYNC              (0x0100u)    /* Sync-Mode  0:UART-Mode / 1:SPI-Mode */
    #define UCSSEL1             (0x0080u)    /* USCI 0 Clock Source Select 1 */
    #define UCSSEL0             (0x0040u)    /* USCI 0 Clock Source Select 0 */
    #define UCSWRST             (0x0001u)    /* USCI Software Reset */
    #define UCCKPH              (0x8000u)    /* Sync. Mode: Clock Phase */
    #define UCCKPL              (0x4000u)    /* Sync. Mode: Clock Polarity */
    #define UCMST               (0x0800u)    /* Sync. Mode: Master Select */
    //#define res               (0x0020u)    /* reserved */
    //#define res               (0x0010u)    /* reserved */
    //#define res               (0x0008u)    /* reserved */
    //#define res               (0x0004u)    /* reserved */
    #define UCSTEM             (0x0002u)    /* USCI STE Mode */

    Jeff

  • Jeff Tenney said:
    It would be good for you to double check the header file you are using to make sure they match these (from IAR):

    I did verify that these do match.

    I've been updating the code a bit more, and while I do have the MSP430 responding, it is still only responding from time to time (Picture below)

    As you can see, the ISR is not being initiated as I've hoped.  The ISR is responding at the end of the transmission, but not in every case.  What would cause the ISR to not be initiated, even if there has been data transmitted?

  • I've continued to discuss the issue on another post. The issue has now become more of an issue with latency, and that I will need to implement modules like DMA to achieve transmitting at the correct moments.

    The issue where the SPI Receive Interrupt was not being triggered at the proper moment has been resolved. There were a couple of things which have resolved the issue, 

    • reset the UCI after the SS pin goes high,
    • changing the UCI control register so that 
      • the clock phase would allow the data to be captured on the first UCLK edge and changed on the following edge,
      • Set the clock polarity to be inactive when it is low

    This fixed the issue where the SPI slave was not matched with the SPI master.  Thank you again for the help.

**Attention** This is a public forum