cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L432 - I2C Address Off By 1-Bit

Nolan L
Associate III
Posted on February 24, 2017 at 06:55

Hi,

I recently brought up the I2C using the STM32CubeMx(4.0) and STM32CUBE_FW_L4_v1.6.0 and I was attempting to write to a slave device with an address of 0x2A.

I noticed that my slave device was NACK-ing back. Upon further inspection, it looks as if the address is shifted to the right by 1-bit, resulting in an address of 0x15 when transmitted on the line.

To test this theory out, I purposefully used an address that is shifted 1-bit to the left: 0x Doing so registered an address of 0x2A on the physical bus which then I was able to hit the register with some data.

I couldn't find any literature that required me to shift my I2C address left by 1-bit to have it address correctly. Has anyone else run into this issue?

My solution is a work around but I would like to understand the root cause of this issue; whether I introduced it or possibly an inherent issue with the HAL drivers?

Thanks!!

Slave Address:

//#define I2C_ADDRESS0x2A
#define I2C_ADDRESS 0x54
#define TXBUFFERSIZE 0x02�?�?�?�?�?�?�?�?�?�?�?�?

Main:

uint8_t i2cTxBuffer[TXBUFFERSIZE] = {0x00, 0x01};
int main(void)
{
/* Initialize HAL, Clocks, GPIO and I2C */
 if(HAL_I2C_Master_Transmit_IT(&hi2c1, (uint16_t)I2C_ADDRESS, (uint8_t*)i2cTxBuffer, TXBUFFERSIZE)!= HAL_OK)
 {
 /* Error_Handler() function is called when error occurs. */
 Error_Handler();
 }
 while (1)
 {
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

I2C Init:

static void MX_I2C1_Init(void)
{
 hi2c1.Instance = I2C1;
 hi2c1.Init.Timing = 0x10915F83;
 hi2c1.Init.OwnAddress1 = 0;
 hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
 hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
 hi2c1.Init.OwnAddress2 = 0;
 hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
 hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
 hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
 if (HAL_I2C_Init(&hi2c1) != HAL_OK)
 {
 Error_Handler();
 }
 /**Configure Analogue filter 
 */
 if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
 {
 Error_Handler();
 }
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Output Using Slave Address 0x54:

0690X00000606OSQAY.png

Output Using Slave Address 0x2A:

0690X00000606OXQAY.png

Datasheet I2C Output:

0690X0000060678QAA.png
1 ACCEPTED SOLUTION

Accepted Solutions
Posted on February 24, 2017 at 09:45

Ah,

... Maybe it's documented in the Cube functions' documentation, I don't Cube so I don't care to check that, you should.

JW

View solution in original post

4 REPLIES 4
Posted on February 24, 2017 at 09:45

Ah,

... Maybe it's documented in the Cube functions' documentation, I don't Cube so I don't care to check that, you should.

JW

Posted on February 24, 2017 at 17:24

I'm not exactly too sure if it is an issue with the address as providing it a larger address will still result in the same location within the register. See snippet of the datasheet below.

I took a deeper dive to see where the slave address is being stored against the datasheets register. On the surface, the value at the register seems correct in both instances; 0x2A and 0x

I2C Slave Address Register Update (stm32l4xx_hal_i2c.c):

static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request)
{
 uint32_t tmpreg = 0U;
 /* Check the parameters */
 assert_param(IS_I2C_ALL_INSTANCE(hi2c->Instance));
 assert_param(IS_TRANSFER_MODE(Mode));
 assert_param(IS_TRANSFER_REQUEST(Request));
 /* Get the CR2 register value */
 tmpreg = hi2c->Instance->CR2;
 /* clear tmpreg specific bits */
 tmpreg &= (uint32_t)~((uint32_t)(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | I2C_CR2_START | I2C_CR2_STOP));
 /* update tmpreg */
 tmpreg |= (uint32_t)(((uint32_t)DevAddress & I2C_CR2_SADD) | (((uint32_t)Size << 16 ) & I2C_CR2_NBYTES) | \
 (uint32_t)Mode | (uint32_t)Request);
 /* update CR2 register */
 hi2c->Instance->CR2 = tmpreg;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

In the instance of writing 0x2A, the register value is 0x202002A:

0690X00000606PgQAI.png

In the instance of writing 0x54, the register value is 0x2020054:

0690X00000606AmQAI.png

These values line up with the register content located in the datasheet (DocID027294 Rev 2):

. 0690X00000606AnQAI.png

I have also placed a watchpoint at that memory location and it does not change until the transfer is complete.

I think my next steps are to obtain a different I2C device and see if I can interface with it there. I shall also attempt this with another NUCLEO board.

Posted on February 24, 2017 at 18:26

Read also the description of I2C_CR2:

0690X000006065EQAQ.png
Posted on February 26, 2017 at 05:12

Yep. You are absolutely correct. Solved my issue and now I am transmitting and receiving just fine. I wish somewhere within the HAL comments explicitly mentioned this. 

Thanks!