Skip to main content
Senior
June 9, 2026
Solved

I2C Problems With KTD2037 Using HAL

  • June 9, 2026
  • 7 replies
  • 208 views

I have a custom board with G491 and an LED driver (Kinetic KTD2037). MCU is the I2C master. Any attempt to read a register using HAL from the KTD2037 fails, ErrorCode = 0x2 (arb lost). Register writes are OK. I can read/write other devices on the same bus OK.

 

The KTD2037 datasheet has this for an I2C register read:

This doesn’t seem consistent with HAL_I2C_Mem_Read() or HAL_I2C_Master_Receive(). 

On a scope HAL_I2C_Mem_Read() results in

  S, 7-bit addr, write, ack, reg addr, ack, Sr, 7-bit addr, read, ack, 0xFF, nack

I try setting the internal register pointer (it may not have one) using HAL_I2C_Master_Transmit(), which works OK. Then I follow it with HAL_I2C_Master_Receive() resulting in

  S, 7-bit addr, read, ack, 0xFF, nack

It looks like the master says arbitration lost because of unexpected nack from the KtTD037.

The KTD2037 datasheet does not mention I2C repeat start.

Any way to read this device without writing my own I2C driver?

Best answer by Saket_Om

Hello ​@mccabehm 

You’re running into a protocol mismatch between the STM32 HAL “memory” APIs and how the KTD2037 actually performs reads, not a physical bus problem.

HAL_I2C_Mem_Read() assumes a memory-like slave:
S → Addr+W → RegAddr → Sr → Addr+R → Data → NACK → P

7 replies

TDK
June 9, 2026

> The KTD2037 datasheet has this for an I2C register read:

This is consistent with a HAL_I2C_Master_Receive call to read 2 bytes. The first byte will be “Register Address” and the second will be “Data”.

HAL_I2C_Mem_Read is not meant for this.

 

If you want to write an address, then read it, you can either do:

HAL_I2C_Mem_Read with a single byte write and a two byte read.

or

HAL_I2C_Master_Transmit with a single byte write plus a HAL_I2C_Mem_Read with a two byte read. These will be separate transactions unlike HAL_I2C_Mem_Read where it will be a repeated start condition.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Karl Yamashita
Principal
June 10, 2026

The KTD2037 is not doing the NACK. It’s the STM32 that does the NACK during READs after it’s done reading the correct number of bytes to notify the slave to stop sending data. That is normal behavior. 

 

When you get HAL_BUSY = 0x02 when calling HAL_I2C_Mem_Read, could mean a number of scenarios. Try debugging and put a breakpoint in HAL_I2C_Mem_Read and see which of the 2 HAL_BUSY it returns from. Then you can narrow it down further. Also check the SR1 and SR2 registers to see which bits are set, if any.

  • if (hi2c->State == HAL_I2C_STATE_READY) will return HAL_BUSY if not equal.
  • Will return HAL_BUSY if it times out.  

 

The datasheet read command doesn’t look correct. But i could be wrong with this particular part.

When reading from a register, you typically want to WRITE the register value, then READ with the device address preceding the data like below. 

 

 

 

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source
mccabehmAuthor
Senior
June 10, 2026

By ErrorCode = 0x2, I mean hi2c2.ErrorCode, not return from HAL_I2C_Mem_Read(). hi2c2.ErrorCode = 0x2 => arbitration lost.

 

 

 

mccabehmAuthor
Senior
June 10, 2026

“HAL_I2C_Mem_Read with a single byte write and a two byte read” works OK.

mccabehmAuthor
Senior
June 11, 2026

I marked “Best answer” too soon.

HAL_I2C_Mem_Read() on a KTD2037 reg returns HAL_OK but the data returned is always 0x02. Reading every reg on the KTD2037 always returns data = 0x02. Some regs have reset values != 0x02, so I know I am not getting actual reg content.

From the KTD2037 datasheet a reg read is expected to be

Notice the KTD2037 expects a read bit (1)  followed by the reg addr. HAL_I2C_Mem_Read() doesn’t do this. HAL_I2C_Master_Transmit() followed by HAL_I2C_Master_Receive() doesn’t do this. When I execute HAL_I2C_Master_Transmit() followed by HAL_I2C_Master_Receive() I don’t get recognizable data.

Another LED driver (TI LP5817) has this for a reg read

The LP5817 first writes the internal reg, does repeat start, then reads data. This is consistent with HAL_I2C_Read_Mem().

I conclude that the HAL I2C APIs won’t work with the KTD2037. I would rather use a different LED driver than write a special I2C driver for the KTD2037.

TDK
June 11, 2026

When the read bit is set, all further data comes from the slave, not from the STM32. This is how I2C works, there is no deviation from this between chips. There is no option to have the STM32 write one byte and then read the next. This would be a violation of I2C.

No doubt “Register Address” is meant to be set in another transaction like what HAL_I2C_Mem_Read does, but the datasheet does a poor job of explaining this.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Saket_OmBest answer
ST Technical Moderator
June 12, 2026

Hello ​@mccabehm 

You’re running into a protocol mismatch between the STM32 HAL “memory” APIs and how the KTD2037 actually performs reads, not a physical bus problem.

HAL_I2C_Mem_Read() assumes a memory-like slave:
S → Addr+W → RegAddr → Sr → Addr+R → Data → NACK → P

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Saket_Om