MSP-EXP430G2ET: Establishing SPI communication

Part Number: MSP-EXP430G2ET
Other Parts Discussed in Thread: BOOST-DRV8711, DRV8711

Tool/software:

Hello,

So, I am currently trying to establish SPI communication between the msp430G2 launch pad and the BOOST-DRV8711. The data is being sent out from the msp430G2(master), which is correct, but when I try to read the data out of the drv8711 IC (slave), nothing is read. 

Can you review my code and guide me in the right direction? Also, if you need any further documentation, please let me know. 

Below is my current code for establishing SPI communication:

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

#define DUMMY   0x0000

#define SLAVE_CS_OUT    P2OUT
#define SLAVE_CS_DIR    P2DIR
#define SLAVE_CS_PIN    BIT0

//*********************************
// General SPI State Machine*******
//*********************************

typedef enum SPI_ModeEnum{
    IDLE_MODE,
    TX_REG_ADDRESS_MODE,
    RX_REG_ADDRESS_MODE,
    TX_DATA_MODE,
    RX_DATA_MODE,
    TIMEOUT_MODE
} SPI_Mode;

/* Used to track the state of the software state machine*/
SPI_Mode MasterMode = IDLE_MODE;

uint8_t SendUCA0Data(uint8_t val) {
    while (!(IFG2 & UCA0TXIFG));  // Wait for TX buffer readiness
    UCA0TXBUF = val;              // Send the data byte
    while (!(IFG2 & UCA0RXIFG));  // Wait for RX buffer to fill
    return UCA0RXBUF;             // Return received data byte
}

SPI_Mode DRV8711_Write(uint8_t reg_addr, uint16_t data){
    MasterMode = TX_REG_ADDRESS_MODE;

    uint16_t command = (0 << 15) | ((reg_addr & 0x07) << 12) | (data & 0x0FFF);  // Construct 16-bit command

    SLAVE_CS_OUT |= SLAVE_CS_PIN;     // Activate the slave (CS high)

    SendUCA0Data((command >> 8) & 0xFF);  // Send upper 8 bits
    SendUCA0Data(command & 0xFF);         // Send lower 8 bits

    //__bis_SR_register(CPUOFF + GIE);              // Enter LPM0 w/ interrupts

    SLAVE_CS_OUT &= ~SLAVE_CS_PIN;    // Deactivate the slave (CS low)

    return MasterMode;
}

uint16_t DRV8711_Read(uint8_t reg_addr) {
    uint16_t command = (1 << 15) | ((reg_addr & 0x07) << 12);  // Construct 16-bit command for read
    uint16_t received_data = 0;

    SLAVE_CS_OUT |= SLAVE_CS_PIN;     // Activate the slave (CS high)

    // Send the command (Read request)
    SendUCA0Data((command >> 8) & 0xFF);  // Send upper 8 bits
    SendUCA0Data(command & 0xFF);         // Send lower 8 bits

    // Receive the data
    received_data = ((uint16_t)SendUCA0Data(DUMMY) << 8);  // Send dummy and receive upper 8 bits
    received_data |= SendUCA0Data(DUMMY);                 // Send dummy and receive lower 8 bits

    SLAVE_CS_OUT &= ~SLAVE_CS_PIN;    // deactivate the slave (CS low)

    return received_data & 0x0FFF;  // Return only the 12 data bits
}


//*******************************
// Device Initialization ********
//*******************************

// calibrating the clock to 16MHz
void initClockTo16MHz()
{
    if (CALBC1_16MHZ==0xFF)                   // If calibration constant erased
    {
        while(1);                             // do not load, trap CPU!!
    }
    DCOCTL = 0;                               // Select lowest DCOx and MODx settings
    BCSCTL1 = CALBC1_16MHZ;                   // Set DCO
    DCOCTL = CALDCO_16MHZ;
}

void initGPIO() {
    // Configure GPIO for SPI
    P1SEL = BIT1 + BIT2 + BIT4;  // Assign SPI pins
    P1SEL2 = BIT1 + BIT2 + BIT4; // pins 1.1(MISO), 1.2(MOSI), and 1.4(CLK)

    // Configure chip select pin
    SLAVE_CS_DIR |= SLAVE_CS_PIN;   // GPIO pin 2.0 is CS
    SLAVE_CS_OUT &= ~SLAVE_CS_PIN;  // CS low by default
}

void initSPI() {
    UCA0CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC;  // SPI master, MSB first, synchronous

    UCA0CTL1 |= UCSSEL_2;                     // Use SMCLK
    UCA0BR0 = 0x03;                           // SPI clock divider ~ 5.3MHz
    UCA0BR1 = 0;
    UCA0MCTL = 0;                             // No modulation must be cleared for SPI

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

}


//*****************************
// Main ***********************
// Sends messages *************
//*****************************
int main(void) {
    WDTCTL = WDTPW | WDTHOLD;  // Stop watchdog timer

    initClockTo16MHz(); // calibrate clock to 16MHz
    initGPIO();         // initiate the GPIO pins
    initSPI();          // initiate SPI commands

    //Write to a DRV8711 register
    uint8_t reg_addr = 0x00;    // register 0x00
    uint16_t write_data = 0xC39;  //data transmitted 
    DRV8711_Write(reg_addr, write_data);

    reg_addr = 0x01;    // register 0x01
    write_data = 0xA13;  // data transmitted 
    DRV8711_Write(reg_addr, write_data);

    //Read from a DRV8711 register
    uint8_t reg_addr = 0x07;    // register 0x07
    uint16_t read_data = DRV8711_Read(reg_addr);


}

  • Looking at the Boost-DRV8711 user guide (SLVU967A) Fig 3,  the G2 Launchpad connections appear to be:

    SCS -> P2.3 

    SCK -> P1.5   (UCB0CLK)

    SDO -> P1.6   (UCB0SOMI)

    SDI   -> P1.7   (UCB0SIMO)

    So you should be using UCB0, not UCA0.

    ---------

    > #define SLAVE_CS_PIN BIT0

    To get SCS=P2.3, this should be

    > #define SLAVE_CS_PIN BIT3   // SCS ->P2.3

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

    > SendUCA0Data((command >> 8) & 0xFF); // Send upper 8 bits
    > SendUCA0Data(command & 0xFF); // Send lower 8 bits

    DRV8711_Read() sends 16 bits of command, then 16 bits of DUMMY. Looking at DRV8711 data sheet (SLVSC40H) Fig 18, the response bits start after the first (1+3) request bits, so the first 16 bits is all you need. This might look something like:

    > received_data = (SendUCB0Data((command >> 8) & 0xFF) << 8); // Send upper 8 bits and get back upper bits
    > received_data |= (SendUCB0Data(command & 0xFF) << 0); // Send lower 8 bits and get back lower bits

    (with no DUMMY exchanges at all).

  • Okay, I will implement this. 

    Do you think the signals will pick up unwanted noise if I use jumper cables between the pins (jumper cable ~ 12cm)? 

  • What kind of motors will you use? As I recall brushed motors can be pretty noisy.

    For the SPI in particular: I've seen bit-smear (propagation delay artifact) over 6" cables at 6MHz. Try starting out with the SPI a bit slower (1 or 2MHz maybe). These are short transactions, so SPI speed probably isn't a practical concern.

  • I am using a stepper motor. Okay, I will change to a slower frequency and see how that works. 

    I appreciate your help. 

**Attention** This is a public forum