Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
6 years, 3 months ago.
I2C does not return data
I'm new to I2C protocol.
I want Nucleo L053R8 to communicate with LIS3DH(acceleration sensor) through I2C. However, it does not work.
For a simple test, I'm trying to get WHO_AM_I value of LIS3DH, which should be 0x33. The register is 0x0F
Here is my code. Please give me any advice.
#include "mbed.h" Serial pc(SERIAL_TX, SERIAL_RX); I2C i2c(PB_9, PB_8); // sda, scl int main() { // char cmd = 0x05; char v; pc.printf("start!\r\n"); // i2c.frequency(100000); while (1) { // i2c.write( 0x0F, &cmd, 1, true ); i2c.read( 0x0F, &v, 1 ); pc.printf("%c\r\n",v); wait(2); } }
1 Answer
6 years, 3 months ago.
The first parameter of the I2C operations is the slaveaddress. That address is 0x30 or 0x32 for the LIS3DH and depends of the logic level of the SA0 pin. Obviously you also need to make sure that the I2C pullup resistors are in place, use 4k7.
#include "mbed.h" Serial pc(SERIAL_TX, SERIAL_RX); I2C i2c(PB_9, PB_8); // sda, scl const char address = 0x30; int main() { char reg = 0x0F; // Register address char val; pc.printf ("start!\r\n"); // i2c.frequency (100000); while (1) { i2c.write (address, ®, 1, true ); // Select the register i2c.read (address, &val, 1 ); // Read the value pc.printf ("Reg 0x%0x is 0x%0x\r\n", reg, val); wait(2); } }
Thank you for your advice!
I'm trying to get WHO_AM_I value of LIS3DH, which should be 0x33. The register is 0x0F.
I don't get the value 0x33. Why?
posted by 26 Aug 2018Ah yes, the code above had the wrong register. Fixed now. Try again.
Make sure you have the I2C mode selected on the device (CS pin high) and the correct slaveaddress (SA0 pin low).
posted by 26 Aug 2018The above code works. Thanks a lot!
If possible, can you tell me how to get x acceleration data from LIS3DH? Here is my code. It doesn't work.
#include "mbed.h" Serial pc(SERIAL_TX, SERIAL_RX); I2C i2c(PB_9, PB_8); // sda, scl const char read_address = 0x30; const char write_address = 0x31; int main() { char val_x_l; char val_x_h; char val_x; char reg_out_x_l = 0x28; char reg_out_x_h = 0x29; char dt[2]; pc.printf ("start!\r\n"); // enable x y z axis dt[0] = 0x20; dt[1] = 0x7F; i2c.write (write_address, dt, 2, false ); while (1) { i2c.write (read_address, ®_out_x_l, 1, true ); i2c.read (read_address, &val_x_l, 1 ); i2c.write (read_address, ®_out_x_h, 1, true ); i2c.read (read_address, &val_x_h, 1); val_x = val_x_h << 8 | val_x_l; pc.printf ("val_x is 0x%0x\r\n", val_x); wait(1); } }
You dont need to use a separate read and write address for the slave. That is done automatically by the I2C read/write methods. The problem in your code is probably that val_x is declared as char (8 bits) and you try to force a 16bit value into that char by shifting/bit-or of 2 bytes. Declare val_x as short (int16) or int (int32) and try again:
#include "mbed.h" Serial pc(SERIAL_TX, SERIAL_RX); I2C i2c(PB_9, PB_8); // sda, scl const char address = 0x30; int main() { char val_x_l; char val_x_h; int val_x; char reg_out_x_l = 0x28; char reg_out_x_h = 0x29; char dt[2]; pc.printf ("start!\r\n"); // enable x y z axis dt[0] = 0x20; dt[1] = 0x7F; i2c.write (address, dt, 2, false ); while (1) { i2c.write (address, ®_out_x_l, 1, true ); i2c.read (address, &val_x_l, 1 ); i2c.write (address, ®_out_x_h, 1, true ); i2c.read (address, &val_x_h, 1); val_x = val_x_h << 8 | val_x_l; pc.printf ("val_x is 0x%0x\r\n", val_x); wait(1); } }