2017-02-23 09:55 PM
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:
Output Using Slave Address 0x2A:
Datasheet I2C Output:
Solved! Go to Solution.
2017-02-24 12:45 AM
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
2017-02-24 12:45 AM
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
2017-02-24 09:24 AM
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:
In the instance of writing 0x54, the register value is 0x2020054:
These values line up with the register content located in the datasheet (DocID027294 Rev 2):
.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.
2017-02-24 10:26 AM
Read also the description of I2C_CR2:
2017-02-25 09:12 PM
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!