9 years, 1 month ago.

i2c 16-bit sequential read-write for RDA5807M

I'm trying to interface a RDA7805M FM radio chip.

http://www.seeedstudio.com/wiki/images/8/88/RDA5807M_datasheet_v1.1.pdf

This uses 16-bit wide sequential and index read-write functions.

Firstly does anyone have any working Mbed code for this device? If so then that would probably answer the question.

I have it working with a STM32F429-Discovery board using this guy's code from Github

https://github.com/papadkostas/RDA5807M

So I know this does operate okay, but there are two issues, the i2c address on Mbed is not 0x10(sequential) and 0x11(random), its 0x20 and 0x22 if I do an i2c scan (tried LPC1768 and a KL25Z platform. The other issue is how to access the 16-bit data word's. I have tried this snip that comes from the ST code (changed the i2c.read part) with little success:

My Mbed i2c read snip

int i=0;
        char rcv[1];
        for(i=0; i<13; i=i+2){
            i2c.read(0x20, rcv,1);
            pc.printf("register:  %X =  %X \n",i,rcv[0]);
            buf[i]=snd[0];      
        }
        for(i=1; i<14; i=i+2){
            i2c.read(0x20, rcv,1);
            pc.printf("register:  %X =  %X \n",i,rcv[0]);
             buf[i]=rcv[0];      
        }

Working ST read snip

int8_t i,x=0;
	RDAstatus = UB_I2C3_ReadMultiByte(RDASequential<<1,0x00,14,0);
	for(i=0; i<13; i=i+2){
		RDA5807M_ReadReg[x] = I2C3_DATA[i];
		RDA5807M_ReadReg[x] = RDA5807M_ReadReg[x] << 8;
		x++;
	}
	x = 0;
	for(i=1; i<14; i=i+2){
		RDA5807M_ReadReg[x] = RDA5807M_ReadReg[x] | I2C3_DATA[i];
		x++;
	}

But still have the original bug that the i2c address is wrong on Mbed.

Can anyone help?

Many thanks Paul.

Thanks Wim, that's sorted the 16-bit formatting but I had to add a start address write first as this reads from 0x00. I can now read from any register.

This reads from 0x02

     readadd[0] = 2;        
              
     i2c.write(0x22, readadd, 1);        
     i2c.read(0x22, rcv, 12);  // read 12 bytes for reg 0x02 .. reg 0x07

Problem is I cant write to a register much the same way, by writing the register address first then a second write with my 2 byte data . here is a snip from an Arduino example:

write example

 Wire.beginTransmission(I2C_INDX);
  Wire.write(regNr);
  _write16(registers[regNr]);
  Wire.endTransmission();

There is an 'endTransmission' there, I did try adding i2c.stop() but made no difference.

posted by Paul Staron 30 Mar 2015

The device is a bit of a strange beast. The datasheet given in the link above is unclear or outdated. The device has two access modes (sequential and random) each with its own slaveaddress. In sequential mode, using slaveaddress 0x20, reading always starts at Register address 0x0A and autoincrements from there. In random mode, using slaveaddress 0x22, reading starts at a previously selected Register address and autoincrements from there. See updated code below. The mbed I2C blockwrite methods dont need begin/end transmission as in the arduino libs. The I2C start and stop are included in the mbed libs.

posted by Wim Huiskamp 31 Mar 2015

1 Answer

9 years, 1 month ago.

The mbed libs use the 8bit convention for I2C addresses. You should shift the address left by one bit if its given in the 7 bit format. So 0x10 becomes (0x10 << 1 -> 0x20).

The datasheet given in the link above is unclear or outdated. The device has two access modes (sequential and random) each with its own slaveaddress. In sequential mode, using slaveaddress 0x20, reading always starts at Register address 0x0A and autoincrements from there. In random mode, using slaveaddress 0x22, reading starts at a previously selected Register address and autoincrements from there.

This should get you the values in reg 0x02..0x07

        char reg;
        char rcv[12];

        reg = 0x02;                     // select register
        i2c.write(0x22, &reg,1);  // set selected register 0x02 (random access mode)
        i2c.read(0x22, rcv,12);   // read 12 bytes for reg 0x02 .. reg 0x07

        for(i=0; i<6; i++){
            pc.printf("register:  %X =  %X \n\r", i + 0x02, (rcv[i *2] << 8) | rcv [(i*2) +1] );
        }

posted by Wim Huiskamp 30 Mar 2015