Addresses need to be doubled in SPL for STM8

ken-yapKen Yap wrote 10/10/2021 at 22:47 • 2 min read • Like

While interfacing a DS3231 RTC to a STM8 development board using the Standard Peripherals Library and PlatformIO (BTW, you don't need to build SPL, it's provided by a PlatformIO package), I fell into a simple trap. I assumed that the address wanted by the I2C functions of the SPL was the one stated by the manufacturer. In the wire protocol this is the top 7 bits of the address byte (0x68 in the case of the DS3221) and the bottom bit indicates the direction of data transfer. However the SPL functions want the address shifted one bit left (or doubled if you prefer). This is obvious when looking at this SPL function.

void I2C_Send7bitAddress(uint8_t Address, I2C_Direction_TypeDef Direction)
  /* Check function parameters */

  /* Clear bit0 (direction) just in case */
  Address &= (uint8_t)0xFE;

  /* Send the Address + Direction */
  I2C->DR = (uint8_t)(Address | (uint8_t)Direction);

I assume the SPL writer did this to avoid a runtime left shift of the address parameter, and wanted the SPL user to do this themselves, as the address is usually a constant in the code and the doubling folded by optimisation. Programmers who use the I2C registers directly without SPL will normally take care of this point when setting the address.

Code examples of using I2C with STM8 SPL are a bit thin on the ground, but this is one that helped me.

The embarrassing other problem that prevented my RTC reading routine from working was hardware. I had an unsoldered joint on the B5 (SDA) pin. Now I can see in the PlatformIO debug session (which uses openocd and stm8-gdb) that the correct time and date bytes are returned to the caller.