Search code examples
avravr-gcc

Help needed with the ADXL345 SPI bus to AtMega644


Hi I'm trying to get the SPI bus on a AtMega644 to talk to the ADXL345 accelerometer. I'm always getting a 0 back and I'm not where I'm going wrong. Any help is appreciated. I'm using avr-gcc and not the Arduino code base. Thanks

#define F_CPU 18000000
#define BAUDRATE 115200
#define UBRRVAL (F_CPU/(BAUDRATE*16UL)) -1
#define SPI_CS      PB0
#define DDR_SPI     DDRB
#define DD_MOSI     PB5
#define DD_MIOS     PB6
#define DD_SCK      PB7

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include "serial.h"

/**
 *
 */
void clear_spics(){
    PORTB |= _BV(SPI_CS); // high
    delay_ms(30);
}

/**
 *
 */
void set_spics(){
    PORTB &=~ _BV(SPI_CS); // low
    delay_ms(30);
}

/**
 *
 */
void InitSPI(){
    // make the MOSI, SCK, and SS pins outputs
    DDRB |= ( 1 << DD_MOSI ) | ( 1 << DD_SCK ) | ( 1 << SPI_CS );

    // make sure the MISO pin is input
    DDRB &= ~( 1 << DD_MIOS );

    /* Enable SPI, Master, set clock rate fck/128 */
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);
}

/**
 *
 */
unsigned char WriteByteSPI(unsigned char cReg, unsigned char cData){
    set_spics();
    /* Start transmission send register */
    SPDR = cReg;
    /* Wait for transmission complete */
    while(!(SPSR & (1<<SPIF)))
        { /* NOOP */ }

    clear_spics();
    set_spics();
    SPDR = cData;
    /* Wait for transmission complete */
    while(!(SPSR & (1<<SPIF)))
        { /* NOOP */ }

    clear_spics();
    return SPDR;
}


int  main(){
    char  data;
    USART_Init();
    InitSPI();
    //tell axdl345 use 4 wire spi communication
    WriteByteSPI(0x31,0x00);



    for(;;){
        data = WriteByteSPI(0x36,0);
        send_byte(data);
        delay_ms(2000);
    }

    //never get here
    return 0;
}

Solution

  • this is what I needed. I needed to set the read bit with a 0x80 mask.

    /**
     * This writes to a register with the data passed to the address passed
     * @param unsigned char cReg - the address of the register you wish to write to
     * @param unsigned char cData - the data you wish to write to the register
     */
    unsigned char WriteByteSPI(unsigned char cReg, unsigned char cData){
       set_spics();
       /* Start transmission send register */
       SPDR = cReg;
       /* Wait for transmission complete */
       while(!(SPSR & (1<<SPIF)))
           { /* NOOP */ }
       SPDR = cData;
       /* Wait for transmission complete */
       while(!(SPSR & (1<<SPIF)))
          { /* NOOP */ }
       clear_spics();
       return SPDR;
       }
    
    /**
     * This adds the read bit to the address and passes it to the Write command
     * @param cReg - unsigned char the register you wish to read
     */
    unsigned char ReadByteSPI(unsigned char cReg){
        return WriteByteSPI( (cReg | ADXL345_SPI_READ),0xAA);
    }