Using Pololu L3G4200D in SPI mode with AVR

Can someone please post C code that works with the Pololu L3G4200D and an AVR uC in the SPI mode?

I use 3.3V connected to VDD.

Here is my test code for xmegaA1 running at 32MHz (it doesn’t work, SDO is stuck high):

    PORTF.OUTCLR = PIN4_bm;
    __delay_cycles(F_CPU/400000);
    SPIF.DATA = 0xa6;
    __delay_cycles(F_CPU/500000);
    SPIF.DATA = 0x00;
    __delay_cycles(F_CPU/300000);
    data = SPIF.DATA;
    PORTF.OUTSET = PIN4_bm;

void SetupSPI()
{  
  SPIF.CTRL = SPI_CLK2X_bm | SPI_PRESCALER_DIV16_gc |
  SPI_ENABLE_bm | SPI_MASTER_bm | SPI_MODE_3_gc;
  SPIF.INTCTRL = SPI_INTLVL_OFF_gc;
  /* MOSI and SCK as output. MISO input*/
  PORTF.DIRSET = PIN5_bm | PIN7_bm;
  PORTF.DIRCLR = PIN6_bm;
  /* Init SS pin as output with wired AND and pull-up. */
  PORTF.DIRSET = PIN4_bm;
  /* Set SS output to high. (No slave addressed). */
  PORTF.OUTSET = PIN4_bm;
}

Thanks,

Hello, Szpiro.

The L3G4200D uses I2C, not SPI. We have example code for the Arduino (AVR ATmega328P) here:

github.com/pololu/L3G4200D/tree/master/L3G4200D

The I2C communication is handled by the Arduino “Wire” library. You can see the source code of that library here:

github.com/arduino/Arduino/tree … aries/Wire

–David

I have it working in the I2C mode, but I was hoping to use the easier and faster SPI interface.

Why, if your carrier board does not work in SPI, do you describe SPI usage in your writeup (shown below)?

SPI Communication
To communicate with the L3G4200D in SPI mode, the CS pin (which the board pulls to VDD through a 10 kΩ resistor) must be driven low before the start of an SPI command and allowed to return high after the end of the command. Level shifters on the SPI clock (SPC) and data in (SDI) lines enable SPI communication with microcontrollers operating at the same voltage as VIN (2.5-5.5 V).

In the default 4-wire mode, the gyro transmits data to the SPI master on a dedicated data out (SDO) line. If the SPI interface is configured to use 3-wire mode instead, the SDI line doubles as SDO and is driven by the L3G4200D when it transmits data to the master. A detailed explanation of the SPI interface on the L3G4200D can be found in its datasheet (1MB pdf).

Oops, you are right. The L3G4200D can use SPI. I don’t have any experience with the xmegas, but we do have an OrangutanSPIMaster library that works for several ATmega processors and might help you. You can see the source code if you download the Pololu USB AVR Library.

Do you have an oscilloscope available so you can make sure the AVR is outputting the right signals on MOSI and SCK?

–David

I used my oscilloscope to verify the signals. I used SPI with the xmega and with other AVRs before this; the software is much simpler.

Is it posiible that the 10k pullup resistors are creating a problem? I bought three of them, and if you want me to, I can try to disconnect the pullups according to your instructions.

The pull-up resistors probably aren’t causing a problem. Is there some particular problem you think they would cause?

Are you remembering to drive the CS line low before the start of your SPI command, and let it go high at the end?

Could you describe how everything is powered and hooked up?

–David

Here is a link to a picture of my setup, presently wired for I2C and working well:
picasaweb.google.com/1029303074 … 3432828498

I dont have the schematics ready to show yet.

From the code that I included in the first posting you can see that CS is programmed properly, and O’Scope pictures confirmed all the signals except that SDO did nor budge.

If the problem is mine I will find it!!
I spent quite a bit of time trouble shooting, and this is NOT the first time I used SPI. So, i thought that code and schematics from a successful project with this board would point me in the right direction.

Do you have the code (and maybe schematics) that you used to test the SPI mode of this carrier board?

Thanks

Hello, Amos.

Here is some of the code we use to test the SPI interface on the L3G4200D carriers. It runs on a Baby Orangutan B-328 and uses SPI functions from the Pololu AVR Library, so I am not sure how useful it will be to you (though you can look at the source for the library to see some lower-level code).

#define CS_HIGH() {set_digital_input(PIN_CS, HIGH_IMPEDANCE);}
#define CS_LOW()  {set_digital_output(PIN_CS, 0);}

#define SPI_READ      0x80

char spi_id_test(void)
{
  unsigned char id;

  CS_LOW();
  spi_master_transmit(SPI_READ | 0x0F); // WHO_AM_I
  id = spi_master_transmit(0xFF);
  CS_HIGH();

  if (id != L3G4200D_DEVICE_ID)
  {
    error(ERR_SPI_DEVICE_ID);
    return 0;
  }

  return 1;
}

int main(void)
{
  ...
  CS_HIGH();
  spi_master_init(SPI_SPEED_DIVIDER_4, SPI_SCK_IDLE_HIGH | SPI_MSB_FIRST | SPI_EDGE_TRAILING);

  spi_id_test();
  ...
}

- Kevin