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.

CCS/MSP430F5500: LIS3DH always returns 0xFF on SPI I/F to MSP430F5500

Part Number: MSP430F5500


Tool/software: Code Composer Studio

I am trying to configure LIS3DH chip via SPI İnterface. Here is my code :

#include <msp430.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>


#define CS BIT3 // PORT4, bit3
#define SELECT() do { P4OUT &= ~CS; unsigned int a; for(a=50;a>0;a--); } while ( 0 )
#define DESELECT() do { P4OUT |= CS; } while ( 0 )
#define LIS3DH_REG_WHOAMI 0x0F
#define I_AM_LIS3DH ((uint8_t)0x33)
#define LIS3DH_REG_CTRL1 0x20
#define LIS3DH_REG_CTRL2 0x21
#define LIS3DH_REG_CTRL3 0x22
#define LIS3DH_REG_CTRL4 0x23
#define LIS3DH_REG_CTRL5 0x24
#define LIS3DH_REG_CTRL6 0x25
#define LIS3DH_REG_OUT_X_L 0x28
#define LIS3DH_REG_OUT_Y_L 0x2A
#define LIS3DH_REG_OUT_Z_L 0x2C


typedef struct{
float accel_x;
float accel_y;
float accel_z;
}accel_str;

void InitSPI(void);
int8_t InitMEMS(void);
void setWriteMode(uint8_t addr);
void writeByte(uint8_t data);
void setReadMode(uint8_t addr);
uint8_t readByte();
void read(uint8_t* readData, uint8_t addr, uint8_t numBytes);
void writeRegister(uint8_t addr, uint8_t data);
void accelLoad(accel_str* x_accel);

accel_str x_accel; // main accel struct that contains all sensor outputs

int main(void)
{

WDTCTL = WDTPW + WDTHOLD; // Stop WDT
InitSPI();
InitMEMS();
accelLoad(&x_accel); // get accelerometer results

}

/* P4.5 – UCA1SOMI
P4.4 – UCA1SIMO
P4.0 – UCA1CLK
P4.3 - ChipSelect */

void InitSPI(void){
P4SEL |= BIT0 + BIT4 + BIT5;
P4OUT |= BIT3;
P4DIR |= BIT3;
UCA1CTL1 |= UCSWRST;
UCA1CTL0 = UCCKPL | UCMSB | UCMST | UCMODE_0 | UCSYNC;
UCA1CTL1 = UCSSEL_2;
UCA1BR0 = 32;
UCA1BR1 = 0; //
UCA1MCTL = 0; // No modulation
UCA1CTL1 &= ~UCSWRST;
}

int8_t InitMEMS(void){

uint8_t deviceId;

read(&deviceId, LIS3DH_REG_WHOAMI , 1); // First detect if module is attached

if(deviceId != I_AM_LIS3DH)
return -1; //error

writeRegister(LIS3DH_REG_CTRL1, 0x57); //All axes, normal, 100Hz
writeRegister(LIS3DH_REG_CTRL2, 0x00); // No HighPass filter
writeRegister(LIS3DH_REG_CTRL3, 0x00); // No interrupts
writeRegister(LIS3DH_REG_CTRL4, 0x00); // all defaults
writeRegister(LIS3DH_REG_CTRL5, 0x00); // all defaults
writeRegister(LIS3DH_REG_CTRL6, 0x00); // all defaults

return 1; // success
}

/**
* Write an initial byte
*/
void setWriteMode(uint8_t addr){

while (!(UCA1IFG & UCTXIFG)); // TX buffer ready?
UCA1TXBUF = (addr | 0x00); // 1 = read / 0 = write
while (!(UCA1IFG & UCTXIFG)); // TX buffer ready?

}

/**
* Write a single byte
*/
void writeByte(uint8_t data){

while (!(UCA1IFG & UCTXIFG)); // TX buffer ready?
UCA1TXBUF = data; // send data
while (!(UCA1IFG & UCTXIFG)); // TX buffer ready?

}
/**
* Read a single byte
*/
void setReadMode(uint8_t addr){

while (!(UCA1IFG & UCTXIFG)); // TX buffer ready?
UCA1TXBUF = (addr | 0x80); // 1 = read / 0 = write
while (!(UCA1IFG & UCTXIFG)); // TX buffer ready?

}
uint8_t readByte(){

while (!(UCA1IFG & UCTXIFG)); // TX buffer ready?
UCA1TXBUF = 0xAA; // send garbage
while (!(UCA1IFG & UCTXIFG)); // TX buffer ready?
while (!(UCA1IFG & UCRXIFG)); // RX Received?


return UCA1RXBUF; // Store received data
}

/**
* Reads any number of bytes from a specific address. Make sure that
* the sensor will self-increment its register pointer after subsequent reads
*/
void read(uint8_t* readData, uint8_t addr, uint8_t numBytes){
uint8_t i;
SELECT();

setReadMode(addr);
for(i = 0; i != numBytes; i++){
*readData = readByte();
readData++; // increase to next address
}

DESELECT();
}
/**
* Writes a single byte to a single register
*/
void writeRegister(uint8_t addr, uint8_t data){
SELECT();

setWriteMode(addr);
writeByte(data);

DESELECT();
}

/**
* Get all 3-axis accelerometer readings. Convert from mg to g.
*/
void accelLoad(accel_str* x_accel){
int16_t tmp;
read((uint8_t*)&tmp,LIS3DH_REG_OUT_X_L, 2);
x_accel->accel_x = (tmp * 0.061) / 1000.0;
read((uint8_t*)&tmp,LIS3DH_REG_OUT_Y_L, 2);
x_accel->accel_y = (tmp * 0.061) / 1000.0;
read((uint8_t*)&tmp,LIS3DH_REG_OUT_Z_L , 2);
x_accel->accel_z = (tmp * 0.061) / 1000.0;
}

Problem: the lis3dh register with address 0x0F keeps constant 51 (type of device of something). when I send request to read this register (Reg address plus set MSB bit) via SPI interface Msp430f5500 SPI RX Register gives me 0xFF at first. Is it normal or have I missed something?

 

  • A single SPI transfer always writes a byte and reads a byte, so there will be a new byte in RXBUF afterwards, and RXIFG will be set. This means that you are reading the byte that was received while the address was sent.

    Also, one byte can be written to TXBUF even while the previous byte is still being sent. This means that you cannot use TXIFG to check when the transaction has finished on the bus, and that writeRegister() deselects CS too early.

    The simplest way to handle SPI is with a single function that both writes and reads, and that ensures that RXIFG is always cleared afterwards:

    uint8_t spiTransfer(uint8_t writeData)
    {
        while (!(UCA1IFG & UCTXIFG)); // wait for TX buffer ready
        UCA1TXBUF = writeData;
        while (!(UCA1IFG & UCRXIFG)); // wait for RX buffer ready
        return UCA1RXBUF;
    }
    
    void setWriteMode(uint8_t addr)
    {
        spiTransfer(addr | 0x00);
    }
    
    void setReadMode(uint8_t addr)
    {
        spiTransfer(addr | 0x80);
    }
    
    void writeByte(uint8_t data)
    {
        spiTransfer(data);
    }
    
    uint8_t readByte()
    {
        return spiTransfer(0xAA);
    }
  • I see the value of 0xFF again Can the hardware part be in trouble? :)
  • Problem is solved Thank you very much :) :) :)
  • Hi I have the same problem. Can you tell me how did you solve the issue?

**Attention** This is a public forum