cancel
Showing results for 
Search instead for 
Did you mean: 

Accessing 16 Bit Registers on I2C

ZExpo.1
Senior

What is the function of accessing 16 Bit Resisters available on VL6180 Controller?

1 ACCEPTED SOLUTION

Accepted Solutions

The I2C HAL API should allow you to define 8 or 16-bit wide addressing, and you can read multiple bytes. Registers in slaves typically auto-increment, such that you read 16-bit values as consecutive bytes, and recombine them, often in big-endian form

uint16_t ublox_ReadLength(void)
{
  uint8_t data[2];
  HAL_StatusTypeDef status = HAL_I2C_Mem_Read(&I2CHandle, (0x42 << 1), 0xFD, 1, data, sizeof(data), 100);
  if (status != HAL_OK)
    printf("ublox_ReadLength failed %d %08X\n", status, I2CHandle.ErrorCode);
  return(((uint16_t)data[0] << 8) + (uint16_t)data[1]); // Big Endian
}

The 0xFD register in this case being 1-byte (8-bit) and the data content 2-bytes (16-bit)

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

6 REPLIES 6

The I2C HAL API should allow you to define 8 or 16-bit wide addressing, and you can read multiple bytes. Registers in slaves typically auto-increment, such that you read 16-bit values as consecutive bytes, and recombine them, often in big-endian form

uint16_t ublox_ReadLength(void)
{
  uint8_t data[2];
  HAL_StatusTypeDef status = HAL_I2C_Mem_Read(&I2CHandle, (0x42 << 1), 0xFD, 1, data, sizeof(data), 100);
  if (status != HAL_OK)
    printf("ublox_ReadLength failed %d %08X\n", status, I2CHandle.ErrorCode);
  return(((uint16_t)data[0] << 8) + (uint16_t)data[1]); // Big Endian
}

The 0xFD register in this case being 1-byte (8-bit) and the data content 2-bytes (16-bit)

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

i also have problem with reserver address 0x78 
am dealing with i2c eeprom 
the 7 bit address 0x78 in arduino need to be extracted from the 10 bit address 
using this part 
void writeLexChip(uint16_t TenBits_slave_address, uint8_t firstRegisterByte, uint8_t secondRegisterByte, uint8_t thirdRegisterByte, uint8_t *contentBuffer, uint16_t writeSize) {
ChipOn();
uint16_t slave_address_LSB = TenBits_slave_address & 0x0FF;
uint16_t slave_address_MSB = TenBits_slave_address & 0x300;
slave_address_MSB = slave_address_MSB >> 8;
uint8_t SevenBits_compat_address = 0x78 | slave_address_MSB;
contentBuffer[0] = slave_address_LSB;
contentBuffer[1] = firstRegisterByte;
contentBuffer[2] = secondRegisterByte;
contentBuffer[3] = thirdRegisterByte;
Wire.beginTransmission(SevenBits_compat_address);
Wire.write(contentBuffer, 4 + writeSize);
Wire.endTransmission(true);
Serial.println(F("Write OK"));
ChipOff();
}

now in stm32 nucleo f446re 
and i was very very very happy when i bought it 
thinking that it is very strong than arduino uno 
and after trying every line in the i2c hal 
it cant even show me the i2c eeprom address on i2c scanning
even the i2c scanners on the stm32 cube ide 
cannot deal with 10 bit devices 
when the uno and esp8266 can 
can any one help me 
and sorry for my bad english 

The STM32 wants the 7-bit address in the high order bits, ie 0x78 << 1 is 0xF0

ie Binary pattern 11110xxY xxxxxxxx where x represents the 10-bit address, and Y is the read/write bit

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Then when reading . I should use 0xf0 and in my eeprom data sheet write byte is 0x02 . Then i should use 0xf2

What's the 10-bit slave address?

What's the address within the EEPROM? How wide is that address space? 0-255, 0-65535?

Link to data sheet or salient portions showing expected signalling, addressing, etc.

 

uint16_t  slave_addr = 0x123;

STM32 slave address = ( (0x78 | (slave_addr >> 8)) << 1); // Decompose 10-bit addressing

Byte[0] = (uint8_t)(slave_addr & 0xFF);

Byte[1] = Address within Device (1st)

Byte[2] = Address within Device (2nd)

...

 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

the i2c eeprom doesnt have data sheet 
and after consulting china they sent arduino code can handle 
reading it easilly
and the i2c bsu number on the chip is = TI046B1

and this is the instructions for dealing with the chip 

//We use 10 bits I2C address but Atmega is only compatible with 7 bits address. That's not a problem.
//We just have to trick a little bit because 10 bits addressing is completely fine with the standard I2C physical protocol

//Let's say address = [9876543210] (10 bits)

//Here is how to write communication to a 10bits addressed slave : (A = ACK)
//[START] [0b1111 098W]A [76543210]A [WRITE_1]A [WRITE_2]A ... [WRITE_N]A [STOP]

//We begin with the template '1111 0' in order to talk to 10-bits addressed slaves, followed by 2 address bits, and W.
//Then the first byte we transmit are the 8 following bits of the address, in order to finish the 10 bits addressing.
//Nothing else changes. In order to know if the slave is missing, it's the second ACK that should be checked.


//Read communication (NA = NACK)
//[START] [0b1111 098W]A [76543210]A [RESTART] [0b1111 098R]A [ANSWER_1]A [ANSWER_2]A ... [ANSWER_N]NA [STOP]
//We begin as a standard 10 bits addressed write in order to ask our question to the slave, then we do a restart in order to get the answer

//After the restart, only one byte can be placed (with Read Bit at the end) before reading, so we cant put the full 10 bits address. We put only but the begining of the address.
//The fully adressed component just before the restart will be the only one to answer.

(all data i have)

i will upload the arduino code for more information