2
\$\begingroup\$

As the title suggests, im interfacing with the BME688 using I2C. The signal I captured using my logic analyzer is shown below. The slave address is 0x76 and register address im trying to read is 0xD0. The slave should return 0x61 but no data is returned by the slave whatsoever.

The master code is running on one of the AM335X Programmable Real-Time Units (PRUs) on a Beaglebone Black. The code is written in PASM and quite long, though the sections of code that matter are linked below:

.macro I2C_WAIT_BY_STOP
.mparam reg
_CHECK:
LBCO reg.w0, C_I2C1, I2C_CON, 2
QBBS _CHECK, reg.t1
.endm


.macro I2C_READ_INIT
.mparam reg, busaddr, regaddr
//slave address
MOV         reg.w0, busaddr
SBCO        reg.w0, C_I2C1, I2C_SA, 2

//number of bytes to send
MOV         reg.b0, 1
SBCO        reg.b0, C_I2C1, I2C_CNT, 1

//fill the FIFO
MOV         reg, regaddr
SBCO        reg.b0, C_I2C1, I2C_DATA, 1
_I2C1_WAIT_BUS_FREE:
LBCO        reg, C_I2C1, I2C_STAT_RAW, 4
QBBS        _I2C1_WAIT_BUS_FREE, reg.t12

MOV         reg.w0, I2C_CMD_ENABLE | I2C_CMD_TX | I2C_CMD_START | I2C_CMD_MST |    I2C_CMD_STOP
SBCO        reg.w0, C_I2C1, I2C_CON, 2

I2C_WAIT_BY_STOP reg
.endm

Here I2C_XX are bitmasks or register offsets and C_I2C1 is the I2C1 control register. The Techinal Reference Manual can be found here with I2C registers starting from Page 4601. The linked code writes the slave address to the appropriate register, followed by the number of bytes to send (just 1, the register address). Then the register address is added to the FIFO. When the bus is free, the control register is set with the appropriate bits. These bits enable the module, go into transmission mode, set a start condition, set the module as master, and set a stop condition. Then I2C_WAIT_BY_STOP loops until a new stop condition is received.

What am I doing wrong here?

EDIT: I added the I2C read diagram of the BME688 BME688 I2C Read. I was of the understanding that after sending the slave addr + reg addr the device should respond with the register value in the form of a data packet?

I2C SDA and SCL Signal

\$\endgroup\$
4
  • 2
    \$\begingroup\$ I don't see your code trying to read back anything. What do you expect or assume to happen after you have transmitted out the I2C address and register address what to read? \$\endgroup\$
    – Justme
    Nov 28, 2023 at 13:49
  • \$\begingroup\$ Oscilloscope recommended. I²C can have problems that are maked with a logic analyser, i.e. not correctly configured bus pins are visible on a scope only. \$\endgroup\$
    – Turbo J
    Nov 28, 2023 at 13:52
  • 1
    \$\begingroup\$ @TurboJ Sure a scope can reveal problems not seen by logic analyzer, but also the code does nothing to read the data out, so scope will not help here. \$\endgroup\$
    – Justme
    Nov 28, 2023 at 13:56
  • \$\begingroup\$ @Justme I edited the question to clarify your question \$\endgroup\$
    – lrdewaal
    Nov 28, 2023 at 13:58

2 Answers 2

1
\$\begingroup\$

Your understanding of how I2C is incorrect.

If the master wants to read data out from a slave, the master must transfer the data out from slave with a read operation.

A slave is not allowed or can't do that, because the clock is an input only on a slave.

So basically, your code starts an I2C write transfer operation with slave addess and register index you want to read, and leave the data transmission there.

The code should start a new data transfer operation for I2C read operation with slave address and transfer the amount of bytes out from the slave you want.

\$\endgroup\$
0
\$\begingroup\$

Okay, I was just being silly. I forgot to set the I2C module in receiver mode after transmitting the message. The updated PASM code is:

.macro I2C_WAIT_BY_STOP
.mparam reg
_CHECK:
LBCO reg.w0, C_I2C1, I2C_CON, 2
QBBS _CHECK, reg.t1
.endm


.macro I2C_READ_INIT
.mparam reg, busaddr, regaddr
//slave address
MOV         reg.w0, busaddr
SBCO        reg.w0, C_I2C1, I2C_SA, 2

//number of bytes to send
MOV         reg.b0, 1
SBCO        reg.b0, C_I2C1, I2C_CNT, 1

//fill the FIFO
MOV         reg, regaddr
SBCO        reg.b0, C_I2C1, I2C_DATA, 1
_I2C1_WAIT_BUS_FREE:
LBCO        reg, C_I2C1, I2C_STAT_RAW, 4
QBBS        _I2C1_WAIT_BUS_FREE, reg.t12

MOV         reg.w0, I2C_CMD_ENABLE | I2C_CMD_TX | I2C_CMD_START | I2C_CMD_MST |    I2C_CMD_STOP
SBCO        reg.w0, C_I2C1, I2C_CON, 2

I2C_WAIT_BY_STOP reg

// Put device in receiver mode
MOV         reg.w0, I2C_CMD_ENABLE | I2C_CMD_RX | I2C_CMD_START | I2C_CMD_MST | I2C_CMD_STOP
SBCO        reg.w0, C_I2C1, I2C_CON, 2

I2C_WAIT_BY_STOP reg

.endm
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.