Read not working in i2c.transfer

Documentation for i2c.transfer is minimal, but I need it to be able to read I2C in an interrupt routine.

Write works fine. The read looks good on the bus, including the read data. However, no data in the receive buffer rdat. What am I doing wrong?

DigitalOut green_led(PB_3);
I2C i2c(PB_7, PB_6);

int main() {
green_led = 0;

char wdat[2];
char rdat[2];
int r;
event_callback_t writex;

wdat[0] = 0x87; // addr to read from

i2c.frequency(400000);
r = i2c.transfer(0xE0, wdat, 1, rdat, 1, writex,I2C_EVENT_TRANSFER_COMPLETE,false);

while(1) {
ThisThread::sleep_for(1000ms);
green_led = !green_led;
}
}

Hello,

usually is good to share informations about used target board/MCU and MbedOs version.

You write something but your code just send something and then nothing. But if i uderstand how this is working, you have to call transfer, check r variable for OK transfer start and then wait until callback is called, then should be some data in rdat buffer.

BR, Jan

Correct. there is no data returned in rdat, even though the data is seen with a protocol analyser on the I2C bus.

Apologies for the confused post. I am new at this. The code is running on a NUCLEO -L432KC using Mbed Studio.

The full code is:
#include <mbed.h>

DigitalOut green_led(PB_3);
I2C i2c(PB_7, PB_6);

int main() { //================================================================

green_led = 0;

char wdat[2];
char rdat[3];
int r;

event_callback_t writex;

wdat[0] = 0x87;
wdat[1] = 0xa5;
rdat[0] = 0x00;
rdat[1] = 0x0;

i2c.frequency(400000);

r = i2c.transfer(0xE0, wdat, 1, rdat, 1, writex,I2C_EVENT_TRANSFER_COMPLETE,false);
printf(“rdat[0]=0x%02x\n”,rdat[0]);
printf(“rdat[1]=0x%02x\n”,rdat[1]);

while(1) {
ThisThread::sleep_for(1000ms);
green_led = !green_led;
}

}

Please try to use correct code formating, it is done via these 3 symbols ``` before and after your code.

I think this is not how this works, it is async method. So you can not read it immediately after calling the transfer method. The MCU is much more faster then I2C transaction. I am not sure but I believe it works like in example below (I don’t have anything for testing at the moment)

#include <mbed.h>

DigitalOut green_led(PB_3);
I2C i2c(PB_7, PB_6);

volatile bool tranComplet = false;

void TranCallback(int event){
    if(event & I2C_EVENT_TRANSFER_COMPLETE) {
        tranComplet = true;
    } 
}

int main() { //================================================================
    printf("Test app start\n");	
    wdat[0] = 0x87;
	wdat[1] = 0xa5;
	rdat[0] = 0x00;
	rdat[1] = 0x0;

	i2c.frequency(400000);

    if(i2c.transfer(0xE0, wdat, 1, rdat, 1, &TranCallback ,I2C_EVENT_TRANSFER_COMPLETE,false) == 0){
        printf("Transfer started, wait...\n");
    }

	while(1) {
		if(tranComplet){
			printf(“rdat[0]=0x%02x\n”,rdat[0]);
			printf(“rdat[1]=0x%02x\n”,rdat[1]);
            tranComplet = false;
		}
		ThisThread::sleep_for(1000ms);
		green_led = !green_led;
	}
}

BR, Jan

1 Like

Thanks for the great feedback.

It seems very reasonable, and I will try it.