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.

Interfacing to accelerometer using SPI



Hi,

I'm trying to interface an Analog ADXL345 accelerometer to a T4MC1294 launchpad via SPI. I'm trying to use the SPI peripheral library of the TI RTOS to do so.

I've just got a few questions about the SPI API.

As far as I understand it, the SPI_transfer() function both reads and writes the specified number of bytes at the same time. Does that mean I need to specify a buffer with two bytes and tell the function to read two bytes in order to reproduce a timing diagram as seen below.

The write makes perfect sense, two times 8 bits in the txBuffer.

On the read however I'm unsure. Do I use two two byte buffers and have txBuffer[0] = address, txBuffer[1] = XXX, rxBuffer[0] = XXX, rxBuffer[1] = data? Or do I use two one byte buffers?

I'm also not sure how exactly to wire everything. PD0 and PD1 are SSI2XDAT0 and SSI2XDAT1 respectively according to EK_TM4C1294XL.c, which the board.h points to (well, its .h file at least). That gives me no idea which one is the master input and which one is the master output.


Here's the relevant code I'm running.

#define SPI_MSG_LENGTH    2
unsigned char masterRxBuffer[SPI_MSG_LENGTH] = {0,0};
unsigned char masterTxBuffer[SPI_MSG_LENGTH] = {0,0};


/*
 * ======== ADXL345Init ========
 * Initialise the ADXL345 over spi
 * Consider adding in methods of using different spi units per call
 */

SPI_Handle masterSpi;
SPI_Params spiParams;

void ADXL345Init(void){
    SPI_Transaction masterTransaction;

    SPI_Params_init(&spiParams);
    spiParams.transferMode = SPI_MODE_BLOCKING;
    spiParams.transferCallbackFxn = NULL;
    spiParams.dataSize = 8;
    spiParams.mode = ENV_SPI_MASTER;	// TM4C1294 is master
    spiParams.bitRate = 1000000;	// set bitrate to 1MHz
    spiParams.frameFormat = ENV_SPI_POL1_PHA1;	// phase and polarity = 1

    /* Initialize SPI handle as default master */
    masterSpi = SPI_open(Board_SPI0, &spiParams);


    if (masterSpi == NULL) {
        System_abort("Error initializing SPI\n");
    }
    else {
        System_printf("SPI initialized\n");
    }


    SPIGetRegister(masterSpi, spiParams, 0, 0x00);	// read device ID to check, if everything is connected correctly


}

/*
 * ======== ADXL345MakeRegPacket ========
 * Make a 8 bit configuration/register packet for ADXL345
 * MultByte is for multi byte reads and writes
 * Direction is read (True) or write (False)
 * Address is a six bit char
 * You still need to follow up with a data char for writes
 */
unsigned char ADXL345MakeRegPacket(unsigned char direction, unsigned char multByte, unsigned char address){
	unsigned char regPacket = 0;

	if(direction){				// enforce boolean nature by using if statements and not just ORing it together (can't always guarantee 0 or 1)
		regPacket |= 0x80;
	}
	if(multByte){
		regPacket |= 0x40;
	}
	if(address < 64){
		regPacket |= address;
	}
	else{
		System_printf("SPI reg address out of range with %d", address);
	}
	return regPacket;
}

/*
 * ======== SPIGetRegister ========
 *
 */
void SPIGetRegister(SPI_Handle spiHandle, SPI_Params spiParams, unsigned char multByte, unsigned char regAddress){
	SPI_Transaction spiTransaction;
	spiTransaction.count = 2;
	spiTransaction.txBuf = (Ptr)masterTxBuffer;
	spiTransaction.rxBuf = (Ptr)masterRxBuffer;
    Bool transferOK = 0;

    masterTxBuffer[0] = ADXL345MakeRegPacket(1, multByte, regAddress);
    transferOK = SPI_transfer(spiHandle, &spiTransaction);
    if (!transferOK) {
    /* Error in SPI transfer or transfer is already in progress */
    }

}

When I run this I get masterRxBuffer = {0x00,0x24}, masterTxBuffer = {0xC4, 0x00} with an error of "No source available for "0x0" " after running

transferOK = SPI_transfer(spiHandle, &spiTransaction);

from the getRegister call during initialisation. The relevant register (0x00) should return the device ID, but instead I always end up with the above conditions. I correctly have masterTxBuffer = {0x80,00} before calling SPI_transfer and masterRxBuffer = {0x00,0x00}.

I have it wired as:

SCL = PD3

FSS = PD2

MISO = PD1

MOSI = PD0 (though the pin configuration for MISO and MOSI doesn't seem to make a difference, which leads me to bellieve I'm doing something more fundamentally wrong during initialisation or operation and I'm not even sending garbage. The buffer contents after the SPI_transfer() function remains the same no matter the MISO/MOSI wiring)

I haven't yet looked at all of the signals under scope, but hopefully I'll be able to get my hands on one tomorrow to do that.

Is there anything you can spot that I'm doing wrong there?

Sorry, if this is in the wrong forum for this issue.

Thanks,

Vincent

  • Vincent,

    Sorry for the delayed response. Yes you are right, the SPI_transfer function performs a read and write at the same time. The contents of your txBuffer are shifted out to slave and at the same time, the contents of the slaves register is shifted out to your rxBuffer.

    From the timing diagram, to perform a write to the device you write out 2 bytes. txBuffer[0] = 0 MB A5 A4 A3 A2 A1 A0. The MSB is a 0 signifying a write and the next bit is MB (not sure, check the datasheet for what this but should be), then the last 6 bits are the register address you want to write to on the slave. txBuffer[1] is the data byte you are writing out to the slave.

    Looking at the devices datasheet, PDO is master input and PD1 is master output.

    In reading register 0x00 a transaction of 2 bytes is needed.  txBuffer[0] should be 0x80, with the MSB indicating a read, still not sure what MB bit is but the remaining 6 bits should be the address of the register(0x00) in this case. txBuffer[1] is a don't care. rxBuffer[0] can be anything, the device starts clocking out the contents of the register on the second byte transfer, so rxBuffer[1] should contain the resulting value from the slave.

    Let me know if this helps.

    Moses

  • Hello Moses,

    So I've got a question about the SPI read.

    I'm trying to read the Entire FIFO buffer of ADXL375 at once, so it would be DATAX0 ,DATAX1, DATAY0.....

    To read the FIFO buffer I need to perform a multiple byte read, so the values for my txBuf could be on txBuf[0] - address of DATAX0 txBuf[1]- address of DATAX1..? and perform a transaction with 32 frames at a time? or I can just perform a trasaction with 2 frames at a time?

    Thank you,

    If you could post a document or a commentary explaining better who the SPI transaction works, because on the TIRTOS documents is quite confusing, I figured out the explanation you gave above my test and trial.

    once again, Thank you

    Patryk da Fonseca

  • Hi,
    can u send m complete code "for above interfacing" make it soon.
  • Rahul,

    Not sure what you are asking for. Is it relevant to this thread? Maybe best to start a new thread and state your question clearly.

    ~Ramsey