I2C Not Receiving Values Correctly

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

cross mob
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

I am not a big fan of I2C and avoid it where ever possible but I have a MPU6050 gyro/accel sensor using it and I guess its time to learn how to use I2C in the PSoC Creator.  Looking at it on the scope, it seems to be waking up the sensor and the sensor seems to be returning values that change if the sensor is shaken or moved.  But the values don't seem to be getting received by the uController.  I have been using an Arduino code to sort of give me some direction, but the only thing I hate more then I2C is Arduino.  I will attach the project file of what I have, but I have been working on it so long I feel like its going down hill at this point.  End goal is I need to be able to get the values from the sensor and modify them for a later project.

0 Likes
1 Solution
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I2C_MasterReadByte(I2C_ACK_DATA) << 8 will always result in 0 (zero). You need a type cast as

(int16)I2C_MasterReadByte(I2C_ACK_DATA) << 8

Byte I2C interface is quite simple: After setting up the component and starting it you use

    I2C_MasterSendStart(DeviceAddress,I2C_WRITE_XFER_MODE);    // Initialize a transaction for writing

    I2C_MasterWriteByte(Register);                // Indicate which register you want to write to

    I2C_MasterWriteByte(Value);                // Write to register

    I2C_MasterSendStop();                    // End of transaction

When you want to read from a device you use (example for reading two bytes

    I2C_MasterSendStart(DeviceAddress,I2C_WRITE_XFER_MODE);    // Initialize a transaction for writing

    I2C_MasterWrite(Register);                // Indicate which register you want to write to

    I2C_MasterSendRestart(DeviceAddress,I2C_READ_XFER_MODE);

    I2C_MasterReadByte(I2C_ACK_DATA);            // Read from register

    I2C_MasterReadByte(I2C_NAK_DATA);            // Read from register, last byte is NAKed

    I2C_MasterSendStop();                    // End of transaction

Not too difficult. Keep in mind that most of the APIs (except those for reading a byte) return a status byte which, when non-zero indicate an error condition.

Bob

View solution in original post

0 Likes
3 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I2C_MasterReadByte(I2C_ACK_DATA) << 8 will always result in 0 (zero). You need a type cast as

(int16)I2C_MasterReadByte(I2C_ACK_DATA) << 8

Byte I2C interface is quite simple: After setting up the component and starting it you use

    I2C_MasterSendStart(DeviceAddress,I2C_WRITE_XFER_MODE);    // Initialize a transaction for writing

    I2C_MasterWriteByte(Register);                // Indicate which register you want to write to

    I2C_MasterWriteByte(Value);                // Write to register

    I2C_MasterSendStop();                    // End of transaction

When you want to read from a device you use (example for reading two bytes

    I2C_MasterSendStart(DeviceAddress,I2C_WRITE_XFER_MODE);    // Initialize a transaction for writing

    I2C_MasterWrite(Register);                // Indicate which register you want to write to

    I2C_MasterSendRestart(DeviceAddress,I2C_READ_XFER_MODE);

    I2C_MasterReadByte(I2C_ACK_DATA);            // Read from register

    I2C_MasterReadByte(I2C_NAK_DATA);            // Read from register, last byte is NAKed

    I2C_MasterSendStop();                    // End of transaction

Not too difficult. Keep in mind that most of the APIs (except those for reading a byte) return a status byte which, when non-zero indicate an error condition.

Bob

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

I have implemented some of your suggestions.  The original work space seems to have corrupted so I re-wrote it out and attached a copy of the new version.  Instead of trying to have the data saved as 16 bit values, I am trying to just get each byte saved to its own variable and I will worry about 16 bit values afterward.  Again it is still running correctly looking on the scope, but the uC is not saving the values returned to it.  I had a similar problem once with SPI communication, and it came down to having a check for making sure the uC had finished reading a byte before beginning another command.  Would adding something similar to that be required here, a line something like this?

while((I2C_MasterStatus() & I2C_MSTAT_RD_CMPLT) != I2C_MSTAT_RD_CMPLT)

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

After looking it over again this weekend, I found that part of the problem is the bidirectional level shifter I was using will not work with I2C.  I was using a TXB0104 and gets confused by the I2C pull up resistors.  I switched to a simple MOSFET based bidirectional level shifter to combat this and this was the final code;

Thanks for the help.