Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

MPU-9250 SPI Interfacing Issue with PIC24: WHOAMI Register Reads Incorrectly.

Status
Not open for further replies.

Je_J

Newbie level 1
Joined
Mar 10, 2016
Messages
1
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
26
Hello all! This is my first post.

I am having an unusual issue reading data from an Invensense MPU-9250 in SPI mode with a PIC24F64GB002 microcontroller. According to page 44 of the MPU-9250 register map (http://43zrtwysvxb2gf29r5o0athu.wpe...ent/uploads/2015/02/MPU-9250-Register-Map.pdf) the WHOAMI is supposed to return a default value of 0x71 (it also says that the reset value is 0x68 so I'm not sure which), however in debug mode my microcontroller reads 0x73 and my oscilloscope confirms this.

I also noticed something quite odd with subsequent reads of the WHOAMI register on my oscilloscope. The value changes and the MPU-9250 even transmits data while the microcontroller is writing data.

**broken link removed**

I am having the microcontroller transmit 0x00 to read data from the MPU-9250 and I'm assuming that all of MPU's registers at x address are 1 byte.

Here are several things I tried:
  • lowering the SPI clock from the 1 MHz maximum to 500 kHz.
  • all four SPI modes controlled by CKE and CKP bits in the SPIxCON1 register (the MPU's datasheet indicates a high level idle state and data transition on falling edge, http://43zrtwysvxb2gf29r5o0athu.wpe...ontent/uploads/2015/02/MPU-9250-Datasheet.pdf, page 16).
  • I2C mode (the WHOAMI register still returns 0x73, however subsequent reads of the same register returns the same value).
  • asserting the CS line before a transfer and de-asserting it right after
  • setting the interface to SPI in the USER_CTRL register

I would prefer to use SPI mode because of it's higher data rate, but I will use I2C if necessary.

Here is my code:

mpu9250.c
Code:
#include "mpu9250.h"
#include "spi.h"
#include "mpu9250RegisterMap.h"
#include <xc.h>

#define GYRO_SENSITIVITY 131; //250 dps
#define ACCEL_SENSITIVITY 16384; //+/- 2g

void InitMPU() {
    InitSPI(MPU_SPI_BUS);
    
    //assert CS line
    LATBbits.LATB3 = 0;
    
//    //set interface to SPI
//    WriteMPUWriteCommand(MPU9250_USER_CTRL, 0b00010000);
//    //set sample rate to 8000/1+7 = 1000 Hz
//    WriteMPUWriteCommand(MPU9250_SMPLRT_DIV, 0x07);
//    //disable FSync, 256 Hz DLPF
//    WriteMPUWriteCommand(MPU9250_CONFIG, 0x00);
//    //disable gyro self-tests, set scale to 250 dps, set Fchoice_b to 0b00
//    WriteMPUWriteCommand(MPU9250_GYRO_CONFIG, 0x00);
//    //disable accel self-tests, set scale to +/- 2g, no DHPF
//    WriteMPUWriteCommand(MPU9250_ACCEL_CONFIG, 0x00);
//    //disable FIFO buffer
//    WriteMPUWriteCommand(MPU9250_FIFO_EN, 0x00);
//    //reset sensor signal path
//    WriteMPUWriteCommand(MPU9250_SIGNAL_PATH_RESET, 0x00);
//    //set clock source to gyro with PLL
//    WriteMPUWriteCommand(MPU9250_PWR_MGMT_1, 0b10000011);

    char data = WriteMPUReadCommand(MPU9250_WHO_AM_I);
    char data2 = WriteMPUReadCommand(MPU9250_WHO_AM_I);
    char data3 = WriteMPUReadCommand(MPU9250_WHO_AM_I);
    char data4 = WriteMPUReadCommand(MPU9250_WHO_AM_I);
}

void WriteMPUWriteCommand(char command, char data) { 
    WriteSPIByte(command, MPU_SPI_BUS);
    //discard read byte
    ReadSPIByte(MPU_SPI_BUS);
    WriteSPIByte(data, MPU_SPI_BUS);
    //discard read byte
    ReadSPIByte(MPU_SPI_BUS);
}

char WriteMPUReadCommand(char command) {
    
    WriteSPIByte(command | 0x80, MPU_SPI_BUS);
    //discard read byte
    ReadSPIByte(MPU_SPI_BUS);
    return ReadMPUData();
}

char ReadMPUData() {
    WriteSPIByte(0x00, MPU_SPI_BUS);
    return ReadSPIByte(MPU_SPI_BUS);
}

spi.c
Code:
#include "spi.h"
#include <xc.h>

//forward declarations
void LoadSPIRegisters(int numSPIBus);

//member variables
static volatile unsigned int *SPIxSTAT = 0x00,
                        *SPIxCON1 = 0x00,
                        *SPIxCON2 = 0x00,
                        *SPIxBUF = 0x00;
static int currentSPIBus = 0;

//member routines
//public
void InitSPI(int spiBus)
{
    LoadSPIRegisters(spiBus);
    
    //for interupt use
    ClearSPIIntFlag(spiBus);
    SetSPIIntEnable(false, spiBus);
    SetSPIIntPriority(4, spiBus);
    
    //8-bit communication, data sampled at middle, data changes on
    //high-low, disable SS, idle state is high, master mode,
    //1:1 secondary prescaler, 16:1 primary prescaler (1 MHz clock)
    *SPIxCON1 = 0b0000000001111101;
    //disable framing, enable enhanced buffer (FIFO);
    *SPIxCON2 = 0b0000000000000001;
    //turn on SPI module (must be done last)
    *SPIxSTAT = 0b1000000000000000;
    
}

void SetSPIIntEnable(bool enabled, int spiBus)
{
    switch(spiBus)
    {
        case 1:
            IEC0bits.SPI1IE = enabled;
            break;
        case 2:
            IEC2bits.SPI2IE = enabled;
            break;
    }
}

void SetSPIIntPriority(char priority, int spiBus)
{
    switch(spiBus)
    {
        case 1:
            IPC2bits.SPI1IP = priority;
            break;
        case 2:
            IPC8bits.SPI2IP = priority;
            break;
    }
}

void ClearSPIIntFlag(int spiBus)
{
    switch(spiBus)
    {
        case 1:
            IFS0bits.SPI1IF = 0;
            break;
        case 2:
            IFS2bits.SPI2IF = 0;
            break;
    }
}


void WriteSPIByte(char byte, int spiBus)
{
    LoadSPIRegisters(spiBus);
    while(*SPIxSTAT & 0x02){};
    *SPIxBUF = byte;
}

char ReadSPIByte(int spiBus)
{
    LoadSPIRegisters(spiBus);
    while(*SPIxSTAT & 0x20){};
    return *SPIxBUF;
}

//private
void LoadSPIRegisters(int numSPIBus)
{
    if(currentSPIBus != numSPIBus)
    {
        if(numSPIBus == 1)
        {
            SPIxSTAT = &SPI1STAT;
            SPIxCON1 = &SPI1CON1;
            SPIxCON2 = &SPI1CON2;
            SPIxBUF = &SPI1BUF;
        }
        else if(numSPIBus == 2)
        {
            SPIxSTAT = &SPI2STAT;
            SPIxCON1 = &SPI2CON1;
            SPIxCON2 = &SPI2CON2;
            SPIxBUF = &SPI2BUF;
        }
            
        currentSPIBus = numSPIBus;
    }
}

Thanks!
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top