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.

SPI not working on MSP430F5508

Hello,

I recently got some MSP430F5508s to play around with after moving up from the value line series (G2553 was quite lacking in RAM), and am trying to get the USCI SPI module working. Specifically, I believe I'm having trouble using the Port Mapping Controller. I've configured P4.0 and P4.4 as outputs and as the PM_USCIA1 signals (according to the default pin assignments from the pin diagram). My code is based off the Port Mapping example programs from TI and the SPI configuration I was using with the G2553.

Here's my code to initialize and use the SPI module:

void spi_init(void)
{
//1) Set UCSWRST
UCA1CTL1 |= 1; //UCSWRST = 1

//2) Initialize all USCI registers with UCSWRST=1 (including UCxCTL1)
UCA1CTL1 = (2<<6)|1; //BRCLK = SMCLK, UCSWRST = 1
//Set CLK polarity/phase, MSB first, master mode, 3-pin mode, synchronous
UCA1CTL0 = (CLKPHS<<7)|(CLKPOL<<6)|(1<<5)|(0<<4)|(1<<3)|(0<<1)|1;
//Set clock prescalar value
UCA1BR0 = BR;

//3) Configure ports
sbi(P4DIR,PIN_SS);
sbi(P4OUT,PIN_SS);
// MSP430Fx5xx/x6xx Port Configuration via PMAP
PMAPKEYID = 0x2D52; //PMAPKEY = 0x2D52
PMAPCTL = 0x0002; //Allow reconfiguration
P4MAP5 = PM_UCA1SOMI; //P4.5 (MISO)
P4MAP4 = PM_UCA1SIMO; //P4.4 (MOSI)
P4MAP0 = PM_UCA1CLK; //P4.0 (SCLK)
PMAPKEYID = 0x0000; //PMAPKEY = 0x2D52
sbi(P4SEL,PIN_MISO);
sbi(P4SEL,PIN_MOSI);
sbi(P4SEL,PIN_SCLK);
sbi(P4DIR,PIN_MOSI);
sbi(P4DIR,PIN_SCLK);

//4) Clear UCSWRST via software
UCA0CTL1 &= ~(1); //UCSWRST = 0
}

void spi_out(u08 byte)
{
cbi(P4OUT,PIN_SS);
UCA1TXBUF = byte;
while(UCA0STAT & 0x01); //Wait until USCI not busy
sbi(P4OUT,PIN_SS);
}

I've tested P4.0 and 4.4 as I/O and they can output high/low signals just fine, but as soon as the P4SEL bits are set, the lines appear to become inputs (fall from high level down to 0V with a slow time-constant).

Any help would be appreciated!

- Justin Kenny, KJ6KST

4th year Electrical Engineering student, Cal Poly San Luis Obispo

  • Any ideas? I don't think there's much more I can fool around with to try and get this working, other than perhaps trying the B1 module instead, otherwise I guess I'll just have to write an SPI bit-bang driver.

  • You only posted the spi_init and spi_out functions. What about the rest? The port mapping controller can only be accessed once (if not explicitely enabled for subsequent access).
    So if some other part of your code (maybe a library function) already tried a port mapping...

    Why do you remap at all? The default configuraiton is alreeady UCA1CLK on P4.0, UCA1SIMO on P4.4 and UCA1SOMI on P4.5. No remapping necessary.

    Setting P3DIR shouldn't be necessary. The USCI controls the pin direction.

    And why do you use sbi() to set bits?
    A direct assignment is clearer and even faster: And less to type.

    P4DIR |= PIN_SCLK | PIN_MOSI | PIN_MISO;

    Only 3 words, 5 cycles. Instead of 8 words and 14 cycles (one word/cacle saved by using the constant generator for BIT0).
    (p.s.: the cbi pendant is P4OUT &= ~(PIN_SS); )

  • Thanks for the reply, I've made the suggested corrections and I still see no output on the SCLK or MOSI pins (both are low by default and can be pulled high by a 100k resistor, indicating that they remain as inputs). Pins are not being reconfigured anywhere else in the program, and the program at the moment does nothing but set up clocks and transmit data via SPI. The corrected functions and main are below:

    #define PIN_MISO 0x20		//SPI MISO pin = P4.5
    #define PIN_MOSI 0x10 //SPI MOSI pin = P4.4
    #define PIN_SCLK 0x01 //SPI SCLK pin = P4.0
    #define PIN_SS 0x40 //SPI SS pin = P4.6
    #define CLKPOL 1 //Clock idles high
    #define CLKPHS 1 //Bit read on clock rising edge
    #define F_SCLK 1000000 //Clock speed in Hz (F_CLK/256 to F_CLK)
    #define BR (F_CPU/F_SCLK)

    void spi_init(void);
    void spi_out(u08 byte);
    void spi_init(void)
    {
    //1) Set UCSWRST
    UCA1CTL1 |= 1; //UCSWRST = 1

    //2) Initialize all USCI registers with UCSWRST=1 (including UCxCTL1)
    UCA1CTL1 = (2<<6)|1; //BRCLK = SMCLK, UCSWRST = 1
    //Set CLK polarity/phase, MSB first, master mode, 3-pin mode, synchronous
    UCA1CTL0 = (CLKPHS<<7)|(CLKPOL<<6)|(1<<5)|(0<<4)|(1<<3)|(0<<1)|1;
    //Set clock prescalar value
    UCA1BR0 = BR;

    //3) Configure ports
    P4DIR |= PIN_SS;
    P4OUT |= PIN_SS;
    P4SEL |= PIN_MOSI | PIN_SCLK;

    //4) Clear UCSWRST via software
    UCA0CTL1 &= ~(1); //UCSWRST = 0
    }

    void spi_out(u08 byte)
    {
    P4OUT &= ~(PIN_SS);
    UCA1TXBUF = byte;
    while(UCA0STAT & 0x01); //Wait until USCI not busy
    P4OUT |= PIN_SS;
    }
    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD; //Stop watchdog timer

    /* Initialize Clocks */
    UCSCTL6 = 0xC001; //XT2 16MHz
    UCSCTL3 |= (2<<4); //FLL uses REFO
    UCSCTL4 = (2<<8)|(3<<4)|(3); //ACLK = REFOCLK, SMCLK = DCOCLK, MCLK = DCOCLK

    sbi(P5SEL,2);
    sbi(P5SEL,3);

    do
    {
    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags
    SFRIFG1 &= ~OFIFG; // Clear fault flags
    _delay_us(1);
    } while (SFRIFG1 & OFIFG); // Test oscillator fault flag

    UCSCTL4 = (5<<8)|(5<<4)|(5); //ACLK = REFOCLK, SMCLK = DCOCLK, MCLK = DCOCLK
    /* End Clock Initialization */

    /* Main Program Begin */
    spi_init();
    _delay_us(100);

    spi_out(0xA0);

    while(1)
    {
    spi_out(0xA0);

    _delay_ms(500);
    }
    }
  • Justin Kenny said:
    Thanks for the reply, I've made the suggested corrections and I still see no output on the SCLK or MOSI pins


    Doesn't surprise me. Take a look at your code:

    Justin Kenny said:
    UCA1CTL1 |= 1; //UCSWRST = 1

    Justin Kenny said:
    UCA0CTL1 &= ~(1); //UCSWRST = 0
    Justin Kenny said:
    while(UCA0STAT & 0x01); //Wait until USCI not busy
    What do you notice?

    Right, you configure UCA1 and set the pins for UCA1, but release UCA0 for operation and wait for UCA0 not busy.

    p.s.: why don't you use UCSWRST instead of '1' in the instructions? It is clearer, leaves less room for mistakes and makes the comment superfluous.
    Thoses defines are there to be used. Is "2<<8" really setting MCLK to DCOCLK? And if so, why has  "5<<8" some lines below the very same comment?
    Using SELM__DCOCLK in the first, and SELM__XT2CLK in the second statement makes clear: the comment to the second is wrong (and not needed anyway then). In its current form, you'll have to detect that the comment doesn't fit the code and then what is the intended behavior: the one listed in the comment or the one actually implemented?

  • Thanks for all the help! Sad that my problems usually end up being something as small as a typo. The SPI module works now that UCA1 is being released. Yes, my coding style isn't great, and I tend to modify things without modifying the comments when I'm in the middle of a debug like this, I'll clean up my program before continuing my project.

**Attention** This is a public forum