2016-02-12 06:42 AM
Hello,
I've been working with ST HAL libraries for an STM32F030R8T6, using the NUCLEO board, and I'm having some problems with the I2C API. Probably it's a configuration issue but for the love of me, I can't find it. The problem: I call the functionHAL_I2C_Master_Transmit_XX
with address 0x3E. I attach a logic analyzer to the output to check the lines, and the address does not match. The address I see on the line is 0x1F. My main test code is the following. (Just to reproduce this situation) It is a direct copy from the NUCLEO examples. I skip over theSystemClock_Config
andMspInit
, since I can see data on the lines (I2C is sending data correcly) and they don't provide information for my current problem.
#define I2C_ADDRESS 0x3E
#define I2C_TIMING 0x00A51314
uint8_t bTransferRequest = 0;
//(other stuff)
int
main(
void
)
{
HAL_Init();
/* Configure the system clock to 48 MHz */
SystemClock_Config();
/*##-1- Configure the I2C peripheral ######################################*/
I2cHandle.Instance = I2C1;
I2cHandle.Init.Timing = I2C_TIMING;
I2cHandle.Init.OwnAddress1 = I2C_ADDRESS;
I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
I2cHandle.Init.OwnAddress2 = 0xFF;
I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if
(HAL_I2C_Init(&I2cHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/* Enable the Analog I2C Filter */
HAL_I2CEx_ConfigAnalogFilter(&I2cHandle,I2C_ANALOGFILTER_ENABLE);
while
(1){
HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)I2C_ADDRESS, (uint8_t*)&bTransferRequest, 1, 1000);
HAL_Delay(1000);
}
return
0;
}
This code, when examining the output with the logic analyzer, generates the following SDA/SCL sequence.
The Theory:
I went down to the ST code generating the address.
/*******************************************************************************
* @file stm32f0xx_hal_i2c.c
* @author MCD Application Team
* @version V1.3.0
* @date 26-June-2015
******************************************************************************/
//(etc)
static
void
I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode, uint32_t Request){
//(etc)
/* 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;
And from the
http://www.st.com/web/en/resource/technical/document/reference_manual/DM000319pdf
, section 7.2, Control Register 2 (I2C_CR2):Bits 9:8 SADD[9:8]: Slave address bit 9:8 (master mode)
This bit are don’t care
Bits 7:1 SADD[7:1]: Slave address bit 7:1 (master mode)
These bits should be written with the 7-bit slave address to be sent
Bit 0 SADD0: Slave address bit 0 (master mode)
This bit is don’t care
I understand that on 7 bit address mode, the CR2 bits used to generate the address are SADD[7:1] neglecting the value of SADD0. But the ST HAL driver seems to write the value directly (with no shifting at all),
hence the ''transformation'' from 0x3E to 0x1F:
I2C_CR2[7:0] = 0x3E
I2C_CR2[7:1] = 0x1F
This would be fine for 10 bit addresses, but I'm having trouble with 7 bit.
I tested using an I2C temperature sensor (address 0x40). And I can't read anything at all using 0x40, but everything is fine and dandy when using 0x
Could somebody please point me to any configuration flag that I may have missed?
Salut!
#i2c #hal #cubemx #stm32
2016-02-12 07:09 AM
ST, like many others, represent the 7-bit address as the high order 7-bits exactly as they appear on the bus, and the low order R/W bit is determined depending on the nature of the interaction. In these types of systems the address becomes (DATASHEET_ADDR << 1)
2016-02-15 01:00 AM
Thanks for your response.
I was already shifting the address, but was not sure if this was the ''correct'' behaviour. Salut!2016-02-15 02:20 AM
No problem, you just have to watch the system and device data sheets and implementations very carefully. People have represented the 7-bit address in all manner of ways over the decades, so I always double check what the data sheet says, and what the timing diagram illustrates, and then contrast that with how it is handled in the software side driver stack.