I2C - MPU 9150 Problem

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
Hi,

I want to communicate over I2C with MPU9150.
I have a XMC1100 Boot kit and Dave3.

I implemented some functions but i cant trigger the FIFO standard receive interrupt to retrieve read data. A ssample code is here.


#include //Declarations from DAVE3 Code Generation (includes SFR declaration)
#define MPU9150_I2C_ADDRESS 0xD0
#define MPU9150_WHO_AM_I 0x75
#define MPU9150_PWR_MGMT_1 0x6B
uint16_t DataReceive1 = 0x0000;
void receive_data_handler(void);
int write(uint8_t address, uint8_t payload );
int read(uint8_t address);

int main(void)
{
// status_t status; // Declaration of return variable for DAVE3 APIs (toggle comment if required)


DAVE_Init(); // Initialization of DAVE Apps

uint16_t Expect;
write(MPU9150_PWR_MGMT_1,0x00 );
while(1)
{
read(MPU9150_WHO_AM_I);
Expect= DataReceive1;
}
return 0;
}

int write(uint8_t address, uint8_t payload ){
// Configure message data length
I2C001_DataType data1,data2,data3,data4;

// Write access IO expander device PCA9502
// Transmission by the master with start condition,
// I2C write condition and slave address
data1.Data1.TDF_Type = I2C_TDF_MStart;
data1.Data1.Data = (MPU9150_I2C_ADDRESS | I2C_WRITE);
I2C001_WriteData(&I2C001_Handle0,&data1);

// Write to the direction register
data2.Data1.TDF_Type = I2C_TDF_MTxData;
data2.Data1.Data = address;
I2C001_WriteData(&I2C001_Handle0,&data2);

// Write data to configure one bit as output
data3.Data1.TDF_Type = I2C_TDF_MTxData;
data3.Data1.Data = payload;
I2C001_WriteData(&I2C001_Handle0,&data3);

// Stop condition by the master
data4.Data1.TDF_Type = I2C_TDF_MStop;
data4.Data1.Data = ubyteFF;
I2C001_WriteData(&I2C001_Handle0,&data4);

return 1;
}
int read(uint8_t address){

// Configure message data length
I2C001_DataType data1,data2,data3,data4,data5;

// Read access IO expander device PCA9502
// Transmission by the master with start condition,
// I2C write condition and slave address
data1.Data1.TDF_Type = I2C_TDF_MStart;
data1.Data1.Data = (MPU9150_I2C_ADDRESS | I2C_WRITE);
I2C001_WriteData(&I2C001_Handle0,&data1);

// Write data to the device
data2.Data1.TDF_Type = I2C_TDF_MTxData;
data2.Data1.Data = address;
I2C001_WriteData(&I2C001_Handle0,&data2);

// Transmit repeated start condition and slave address
data3.Data1.TDF_Type = I2C_TDF_MRStart;
data3.Data1.Data = MPU9150_I2C_ADDRESS | I2C_READ;
I2C001_WriteData(&I2C001_Handle0,&data3);

// Read one data from slave
data4.Data1.TDF_Type = I2C_TDF_MRxAck1;
data4.Data1.Data = ubyteFF;
I2C001_WriteData(&I2C001_Handle0,&data4);

// Stop condition by the master
data5.Data1.TDF_Type = I2C_TDF_MStop;
data5.Data1.Data = ubyteFF;
I2C001_WriteData(&I2C001_Handle0,&data5);
return 1;
}
// Event Handler( FIFO receive interrupt event) registered with NVIC002 App
void receive_data_handler(void)
{
uint16_t DataReceive1 = 0x0000;
// Read receive buffer, put the data in DataReceive1
I2C001_ReadData(&I2C001_Handle0,&DataReceive1);
}


The received buffer is always 0x00.

What can be the problem? I attached the I2C intterupt to NVIC2 module.
0 Likes
9 Replies
chismo
Employee
Employee
First like received
Hello,

Can you check if the standard receive interrupt has been enabled correctly?

The enable bit is on bit position 30 of RBCTR register in the USIC channel.
You can use the register view of the debugger to see this.

If it is not set, you can insert the following line after the DAVE_Init():

USIC0_CH0->RBCTR |= 0x40000000;

The above assumes channel 0 is used. Change accordingly if channel 1 is used instead.

Regards,
Min Wei
0 Likes
Not applicable
HI,

I checked that register and the value found is 0x51000100 what means that the 30 bit is enable.

Any other thoughts?

I know that the slave is responding because i checked with an analyzer.

TRBSR is 0x200110a

This is where i see a receive buffer error event has been detected. What this mean?
0 Likes
chismo
Employee
Employee
First like received
Hello,

Could it be a problem with the limit setting for the receive buffer interrupt?
0x51000100 means the limit value is set to 1 (bits 8 to 13), which means that the interrupt will be triggered with the reception of a second byte, i.e. exceeding the limit of 1.
From the code, only one byte is received?
If this is the case, can you change the limit value to 0 instead?

The receive buffer error indicates a receive underflow, i.e. reading an empty buffer.

Regards,
Min Wei
0 Likes
Not applicable
Still dont work.

I want to read a word or a byte.

My RXFIFO size is 2 bytes.
The limit is 0.

My TXFIFO size is 2 bytes.
THe limit is 0.

My NVIC priority level is 3.
1773.attach1774.attach
This are USIC0_CH0 registers.

I mention this are the registers for the actual project not for dummy one.

I really don't know why this doesn't trigger the interrupt... I guess is something small that im missing.
0 Likes
chismo
Employee
Employee
First like received
Hello,

The PSR register value indicates a wrong TDF code error on the bit position 1.
But looking at the code, I don't see any problems.

Can you step through the code and see when is the error triggered?
With a working sequence, it will look like the following:

For the write function:
- after the 1st, 2nd and 3rd write => PSR = 0x3604
- after the last write => PSR = 0x3614

For the read function, assuming the PSR is reset to 0 beforehand:
- after the 1st and 2nd write => PSR = 0x3604
- after the 3rd write (restart) => PSR = 0x360C
- after the 4th write (receive data) => PSR = 0xB60C
- after the last write (stop) => PSR = 0xB61C

Regards,
Min Wei
0 Likes
Not applicable
I start to monitor the PSR and the bit that shows a receive event has triggered is set after the NACK is send. Not after the Read like I designed in the code..

And the PSR isn't reseting after first READ function. I attach a complete code. I use the system timer to trigger the READ. Maybe this is messing with the I2C.
/*
* Main.c
*
* Created on: 13.01.2016
* Author: badea
*/

#include //Declarations from DAVE3 Code Generation (includes SFR declaration)


#define MPU9150_SELF_TEST_X 0x0F // R/W
#define MPU9150_SELF_TEST_A 0x10 // R/W
#define MPU9150_SMPLRT_DIV 0x19 // R/W
#define MPU9150_CONFIG 0x1A // R/W
#define MPU9150_GYRO_CONFIG 0x1B // R/W
#define MPU9150_ACCEL_CONFIG 0x1C // R/W
#define MPU9150_FF_THR 0x1D // R/W
#define MPU9150_FF_DUR 0x1E // R/W
#define MPU9150_MOT_THR 0x1F // R/W
#define MPU9150_MOT_DUR 0x20 // R/W
#define MPU9150_ZRMOT_THR 0x21 // R/W
#define MPU9150_ZRMOT_DUR 0x22 // R/W
#define MPU9150_FIFO_EN 0x23 // R/W
#define MPU9150_I2C_MST_CTRL 0x24 // R/W
#define MPU9150_I2C_SLV0_ADDR 0x25 // R/W
#define MPU9150_I2C_SLV0_REG 0x26 // R/W
#define MPU9150_I2C_SLV0_CTRL 0x27 // R/W
#define MPU9150_I2C_SLV1_ADDR 0x28 // R/W
#define MPU9150_I2C_SLV1_REG 0x29 // R/W
#define MPU9150_I2C_SLV1_CTRL 0x2A // R/W
#define MPU9150_I2C_SLV2_ADDR 0x2B // R/W
#define MPU9150_I2C_SLV2_REG 0x2C // R/W
#define MPU9150_I2C_SLV2_CTRL 0x2D // R/W
#define MPU9150_I2C_SLV3_ADDR 0x2E // R/W
#define MPU9150_I2C_SLV3_REG 0x2F // R/W
#define MPU9150_I2C_SLV3_CTRL 0x30 // R/W
#define MPU9150_I2C_SLV4_ADDR 0x31 // R/W
#define MPU9150_I2C_SLV4_REG 0x32 // R/W
#define MPU9150_I2C_SLV4_DO 0x33 // R/W
#define MPU9150_I2C_SLV4_CTRL 0x34 // R/W
#define MPU9150_I2C_SLV4_DI 0x35 // R
#define MPU9150_I2C_MST_STATUS 0x36 // R
#define MPU9150_INT_PIN_CFG 0x37 // R/W
#define MPU9150_INT_ENABLE 0x38 // R/W
#define MPU9150_INT_STATUS 0x3A // R
#define MPU9150_ACCEL_XOUT_H 0x3B // R
#define MPU9150_ACCEL_XOUT_L 0x3C // R
#define MPU9150_ACCEL_YOUT_H 0x3D // R
#define MPU9150_ACCEL_YOUT_L 0x3E // R
#define MPU9150_ACCEL_ZOUT_H 0x3F // R
#define MPU9150_ACCEL_ZOUT_L 0x40 // R
#define MPU9150_TEMP_OUT_H 0x41 // R
#define MPU9150_TEMP_OUT_L 0x42 // R
#define MPU9150_GYRO_XOUT_H 0x43 // R
#define MPU9150_GYRO_XOUT_L 0x44 // R
#define MPU9150_GYRO_YOUT_H 0x45 // R
#define MPU9150_GYRO_YOUT_L 0x46 // R
#define MPU9150_GYRO_ZOUT_H 0x47 // R
#define MPU9150_GYRO_ZOUT_L 0x48 // R
#define MPU9150_EXT_SENS_DATA_00 0x49 // R
#define MPU9150_EXT_SENS_DATA_01 0x4A // R
#define MPU9150_EXT_SENS_DATA_02 0x4B // R
#define MPU9150_EXT_SENS_DATA_03 0x4C // R
#define MPU9150_EXT_SENS_DATA_04 0x4D // R
#define MPU9150_EXT_SENS_DATA_05 0x4E // R
#define MPU9150_EXT_SENS_DATA_06 0x4F // R
#define MPU9150_EXT_SENS_DATA_07 0x50 // R
#define MPU9150_EXT_SENS_DATA_08 0x51 // R
#define MPU9150_EXT_SENS_DATA_09 0x52 // R
#define MPU9150_EXT_SENS_DATA_10 0x53 // R
#define MPU9150_EXT_SENS_DATA_11 0x54 // R
#define MPU9150_EXT_SENS_DATA_12 0x55 // R
#define MPU9150_EXT_SENS_DATA_13 0x56 // R
#define MPU9150_EXT_SENS_DATA_14 0x57 // R
#define MPU9150_EXT_SENS_DATA_15 0x58 // R
#define MPU9150_EXT_SENS_DATA_16 0x59 // R
#define MPU9150_EXT_SENS_DATA_17 0x5A // R
#define MPU9150_EXT_SENS_DATA_18 0x5B // R
#define MPU9150_EXT_SENS_DATA_19 0x5C // R
#define MPU9150_EXT_SENS_DATA_20 0x5D // R
#define MPU9150_EXT_SENS_DATA_21 0x5E // R
#define MPU9150_EXT_SENS_DATA_22 0x5F // R
#define MPU9150_EXT_SENS_DATA_23 0x60 // R
#define MPU9150_MOT_DETECT_STATUS 0x61 // R
#define MPU9150_I2C_SLV0_DO 0x63 // R/W
#define MPU9150_I2C_SLV1_DO 0x64 // R/W
#define MPU9150_I2C_SLV2_DO 0x65 // R/W
#define MPU9150_I2C_SLV3_DO 0x66 // R/W
#define MPU9150_I2C_MST_DELAY_CTRL 0x67 // R/W
#define MPU9150_SIGNAL_PATH_RESET 0x68 // R/W
#define MPU9150_MOT_DETECT_CTRL 0x69 // R/W
#define MPU9150_USER_CTRL 0x6A // R/W
#define MPU9150_PWR_MGMT_1 0x6B // R/W
#define MPU9150_PWR_MGMT_2 0x6C // R/W
#define MPU9150_FIFO_COUNTH 0x72 // R/W
#define MPU9150_FIFO_COUNTL 0x73 // R/W
#define MPU9150_FIFO_R_W 0x74 // R/W
#define MPU9150_WHO_AM_I 0x75 // R
#define MPU9150_I2C_ADDRESS 0xD0

#define NO_XSPY_APPS 1
#define NUMBER_VARIABLES_XSPY1 3

uint16_t GyroX, GyroY, GyroZ, AccX, AccY, AccZ;
uint16_t DataReceived = 0x0000;

DBG002_VariableDescriptionType xSpyTable1[NUMBER_VARIABLES_XSPY1] = {
XSPY_ADD_FLOAT("GyroX", GyroX),
XSPY_ADD_FLOAT("GyroY", GyroY),
XSPY_ADD_FLOAT("GyroZ", GyroZ),
};

DBG002_XSpyDataType xSpyApps[NO_XSPY_APPS];


int MPU_I2C_Write(uint8_t addr,uint8_t *payload, int nbytes);
int MPU_I2C_Read(uint8_t addr);
void receive_data_handler(void);


void my_func_a(void)
{


GyroX = MPU_I2C_Read(MPU9150_GYRO_XOUT_L);
GyroY = MPU_I2C_Read(MPU9150_GYRO_YOUT_L);
GyroZ = MPU_I2C_Read(MPU9150_GYRO_ZOUT_L );
AccX = MPU_I2C_Read(MPU9150_ACCEL_XOUT_L);
AccY = MPU_I2C_Read(MPU9150_ACCEL_YOUT_L);
AccZ = MPU_I2C_Read(MPU9150_ACCEL_ZOUT_L );

IO004_TogglePin(IO004_Handle0);
}

int main(void){

DAVE_Init(); // Initialization of DAVE Apps
DBG002_XspyInit(&xSpyApps[0], xSpyTable1, NUMBER_VARIABLES_XSPY1, DBG002_GID_XSPY1);

uint8_t i2cData[4];

i2cData[0] = 0x07; // Set the sample rate to 1000Hz - 8kHz/(7+1) = 1000Hz
i2cData[1] = 0x00; // Disable FSYNC and set 260 Hz Acc filtering, 256 Hz Gyro filtering, 8 KHz sampling
i2cData[2] = 0x00; // Set Gyro Full Scale Range to ±250deg/s
i2cData[3] = 0x00;

while(MPU_I2C_Write(MPU9150_PWR_MGMT_1,0x00,1));
while(MPU_I2C_Write(0x19,&i2cData,4));


handle_t TimerId;
uint32_t Status = SYSTM001_ERROR;


TimerId = SYSTM001_CreateTimer(100,SYSTM001_PERIODIC,(void*)my_func_a,NULL);
if(TimerId != 0)
{
//Timer is created successfully
Status = SYSTM001_StartTimer(TimerId);
}



while(1)
{
// DBG002_XspyStreamData(&xSpyApps[0]);

}
return 0;
}

int MPU_I2C_Write(uint8_t addr, uint8_t *payload, int nbytes){


I2C001_DataType data1,data2,data3,data4;
uint8_t i;

//Write access IO expander device PCA9502
//Transmission by the master with start condition,
//I2C write condition and slave address
data1.Data1.TDF_Type = I2C_TDF_MStart;
data1.Data1.Data = (MPU9150_I2C_ADDRESS | I2C_WRITE);
I2C001_WriteData(&I2C001_Handle0,&data1);

//Write to the direction register
data2.Data1.TDF_Type = I2C_TDF_MTxData;
data2.Data1.Data = addr;
I2C001_WriteData(&I2C001_Handle0,&data2);

for (i=0;i //Write data to configure one bit as output
data3.Data1.TDF_Type = I2C_TDF_MTxData;
data3.Data1.Data = *(payload++);
I2C001_WriteData(&I2C001_Handle0,&data3);
}

//Stop condition by the master
data4.Data1.TDF_Type = I2C_TDF_MStop;
data4.Data1.Data = ubyteFF;
I2C001_WriteData(&I2C001_Handle0,&data4);


return 0;
}

int MPU_I2C_Read(uint8_t addr){

I2C001_DataType data1,data2,data3,data4,data5,data6;
uint8_t LowValue,HighValue;
int i=0;

data1.Data1.TDF_Type = I2C_TDF_MStart;
data1.Data1.Data = ( MPU9150_I2C_ADDRESS | I2C_WRITE); // Read mode
I2C001_WriteData(&I2C001_Handle0, &data1);

data2.Data1.TDF_Type = I2C_TDF_MTxData;
data2.Data1.Data = addr;
I2C001_WriteData(&I2C001_Handle0,&data2);

data3.Data1.TDF_Type = I2C_TDF_MRStart;
data3.Data1.Data = ( MPU9150_I2C_ADDRESS | I2C_READ); // Read mode
I2C001_WriteData(&I2C001_Handle0,&data3);
while (i<0xFFFFF) i++;
LowValue=DataReceived;

i=0;
data4.Data1.TDF_Type = I2C_TDF_MRxAck0; // TDF_Ack0
data4.Data1.Data = ubyteFF;
I2C001_WriteData(&I2C001_Handle0,&data4);

while (i<0xFFFFF) i++;
HighValue=DataReceived;

HighValue=DataReceived;
data5.Data1.TDF_Type = I2C_TDF_MRxAck1; // TDF_Ack1
data5.Data1.Data = ubyteFF;
I2C001_WriteData(&I2C001_Handle0,&data5);


data6.Data1.TDF_Type = I2C_TDF_MStop; // TDF_Stop
data6.Data1.Data = ubyteFF;
I2C001_WriteData(&I2C001_Handle0,&data6);
LowValue=DataReceived;

return (uint16_t)((HighValue<<8)+LowValue);
}

void receive_data_handler(void){

//uint16_t DataReceived = 0x0000;
// Read receive buffer, put the data in DataReceive1
I2C001_ReadData(&I2C001_Handle0,&DataReceived);
}




If you can take a look.. I don't understand why i can't receive anything.

Thank you,

Valentin
0 Likes
chismo
Employee
Employee
First like received
Hello Valentin,

The sending of the NACK is in response to the received data so I would expect a receive event as I showed previously.
PSR has to be cleared manually by writing to PSCR register.

And previously there was a TDF error. Were you able to eliminate this?

Regards,
Min Wei
0 Likes
Not applicable
Hello


I succesfully read a byte from slave, but when i try to implement a word read the interrupt does not trigger.


I attach the following function for word read.

int MPU_Read_Word(uint8_t reg_address){

// Configure message data length
I2C001_DataType data1,data2,data3,data4,data5,data6;


// Read access IO expander device PCA9502
// Transmission by the master with start condition,
// I2C write condition and slave address
data1.Data1.TDF_Type = I2C_TDF_MStart;
data1.Data1.Data = (MPU9150_I2C_ADDRESS | I2C_WRITE);
I2C001_WriteData(&I2C001_Handle0,&data1);

// Write data to the device
data2.Data1.TDF_Type = I2C_TDF_MTxData;
data2.Data1.Data = reg_address;
I2C001_WriteData(&I2C001_Handle0,&data2);

// Transmit repeated start condition and slave address
data3.Data1.TDF_Type = I2C_TDF_MRStart;
data3.Data1.Data = (MPU9150_I2C_ADDRESS | I2C_READ);
I2C001_WriteData(&I2C001_Handle0,&data3);


// Read first byte from slave
data4.Data1.TDF_Type = I2C_TDF_MRxAck0; //send ACK0 to continue the transfer for a new byte
data4.Data1.Data = ubyteFF;
I2C001_WriteData(&I2C001_Handle0,&data4);

//If I remove the data4 packet I receive only one byte in RECEIVE Buffer and the IRQ is triggered.

// Read the second byte data from slave
data5.Data1.TDF_Type = I2C_TDF_MRxAck1; //send ACK1 to stop the transfer
data5.Data1.Data = ubyteFF;
I2C001_WriteData(&I2C001_Handle0,&data5);

// Stop condition by the master
data6.Data1.TDF_Type = I2C_TDF_MStop;
data6.Data1.Data = ubyteFF;
I2C001_WriteData(&I2C001_Handle0,&data6);

return (uint16_t) DataReceive;

}

void receive_data_handler(void)
{
uint16_t DataReceive1 = 0x0000;
// Read receive buffer, put the data in DataReceive1
I2C001_ReadData(&I2C001_Handle0,&DataReceive);
}



When I acces this function it returns always 0x00 because the receive_data_handler does not trigger. I attached it in NVIC02 App for Standard FIFO receive interrupt.

Is there a flag that need to be cleared or waited to be cleared by system?

I dont think is a TDF error because the code is correct.. I guess i am missing something in the I2C flow control.

Thank you for support.

Valentin Badea
0 Likes
chismo
Employee
Employee
First like received
Hello Valentin,

From the code, the interrupt should be triggered following the write of data5.
Can you check what is the status of the RXFIFO (TRBSR register) just after the write of data5, i.e. first line of the stop condition generation?
Specially:
- SRBI bit will tell us if the event has really occurred (if yes, then it could be that the interrupt is not enabled at the module or system level correctly)
- RBFLVL bit field will indicate the number of bytes received. Here it should be 2 assuming correct reception. Otherwise it can explain why the interrupt is not triggered in the first place.

But taking a step back, I am wondering if the interrupt handler is really needed in the first place.
Would it be easier if the RBUF is simply read twice following the sending of the stop condition within the MPU_Read_Word function?

Regards,
Min Wei
0 Likes