View previous topic :: View next topic |
Author |
Message |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Nov 16, 2019 12:11 am |
|
|
webgiorgio wrote: | However the burst reading isn't working. On the reads after the first one I
get again the value of the first read. It looks like the inclinometer isn't
incrementing the pointer to the next register.
i2c_start(); //start
i2c_write(incl_address); //send device address
i2c_write(0x28); //send address of the register I want to read
i2c_start(); //restart
i2c_write(incl_address+1); //send device read address (device address+1)
ACC_Data0 = i2c_read(); //Read register 28 and ACK
ACC_Data1 = i2c_read(0); //Read register 29 and NACK
i2c_stop(); //stop |
The LSM303 data sheet says on page 21, in section 5.1.2:
Quote: |
In order to read multiple bytes, it is necessary to assert the most
significant bit of the subaddress field. In other words, SUB(7) must
be equal to 1 while SUB(6-0) represents the address of the first
register to be read.
|
This means instead of sending 0x28 you should send 0xA8.
Use:
or
Code: |
i2c_write(0x28 | 0x80); |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19238
|
|
Posted: Sat Nov 16, 2019 2:00 am |
|
|
Must admit I can't see this in the data sheet I have, but it makes sense!...
However as a 'comment', don't add one to get the read address. It is much
more 'intuitive', and 'readable', to use a syntax like:
Code: |
#define READ (1) //bottom bit to specify a read transaction follows
//Then
I2c_write(incl_address | READ); //send device read address
|
It avoids thinking about incrementing addresses, instead you set the READ
bit in the address byte. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Nov 16, 2019 2:15 am |
|
|
I was looking at a newer data sheet. In the data sheet that he links to
in his first post, it's on page 38. It's the 3rd paragraph in this section:
6.1.1 I2C operation
Quote: |
The I2C embedded inside the LSM303AGR behaves like a slave device
and the following protocol must be adhered to. After the start condition
(ST) a slave address is sent, once a slave acknowledge (SAK) has been
returned, an 8-bit sub-address (SUB) is transmitted: the 7 LSb represent
the actual register address while the MSB enables address auto increment.
If the MSb of the SUB field is ‘1’, the SUB (register address) is
automatically increased to allow multiple data read/writes.
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19238
|
|
Posted: Sat Nov 16, 2019 2:23 am |
|
|
That is interesting. I pulled the sheet from the same link when the thread started. No section 6.1.1. Just pulled it again, and the new sheet has this!...
Aaargh.
How to really annoy anyone trying to use the chip.
Old sheet was Rev9, new sheet Rev10.
Makes total 'sense', quite a few chips have a bit that has to be set to
enable multi byte transfers.
With this, I'd use:
Code: |
#define READ (1) //bottom bit to specify a read transaction follows
#define MBYTE (0x80)
//Then
I2c_write(incl_address | READ | MBYTE); //send device read address
//for multi-byte read
|
I just think it makes it clearer what is being done, and since defined
values are evaluated at compile time, costs nothing.
As one other minor comment, change incl_address to INCL_ADDRESS.
There is a 'semi standard' in C to reserve 'ALL CAPITALS', for things
that are #defined. It is useful, since these do behave differently from
things like variables and it helps to 'remind' later that these are #DEFINED
values. Helps avoid silly errors. |
|
|
webgiorgio
Joined: 02 Oct 2009 Posts: 123 Location: Denmark
|
|
Posted: Sat Nov 16, 2019 3:13 am |
|
|
I was reading again and again the chapter 6.1.1 (i2c operation) but I could not understand by myself.
You guys have a lot of experience!
It all works now Thanks!
Code: |
#define READ (1) //0000 0001
#define MULTIBYTE (0x80) //1000 0000
void read_inclinometer_burstMode(){
i2c_start(); //start
i2c_write(INCL_ADDRESS); //send device address
i2c_write(0x28 | MULTIBYTE); //send address of the register I want to read (with bit7 (MSB) equal 1 to enable mutibyte read)
i2c_start(); //restart
i2c_write(INCL_ADDRESS | READ); //send device read address (device address+1)
ACC_Data0 = i2c_read(); //Read register 28 and ACK
ACC_Data1 = i2c_read(); //Read register 29 and ACK
ACC_Data2 = i2c_read(); //Read register 2A and ACK
ACC_Data3 = i2c_read(); //Read register 2B and ACK
ACC_Data4 = i2c_read(); //Read register 2C and ACK
ACC_Data5 = i2c_read(0); //Read register 2D and NACK
i2c_stop();
} |
|
|
|
|