2017-07-17 08:09 AM
Hi,
i have multiple slaves on an I2C bus on STM32F4.
Since a 'I2C_HandleTypeDef hi2c_x;' contains also fields like 'DevAddress', do i need one HandleTypeDef per slave device on the bus or should they share one handle? Sorry if its a trivial question i just want to clarify whats the proper approach and couldnt find the answer in the HAL Driver description documents.
Thanks for your help,
Patrick
#stm32f4 #i2c2017-07-17 08:43 AM
Hello!! you don't need to have one handle per slave.
The 'DevAddress' field you mention is filled internaly.
In every HAL_I2C... transaction function you can put the external device address you want to transact.
2017-07-17 09:34 AM
Hi,
thanks for your answer.
Does HAL take care of multiple slaves accessing the bus? I have a framework of processes which access one bus. Do i have to write myself a bus manager module which handles access in queues?
I assume my multiple processes overwrite each others I2C address in the 'DevAdress' member of their shared I2C handle 'hi2c'. Thats why i thought i maybe need a separate handle for each slave...
I also would like to learn more about the available HAL functions to coordinate such a multiple actor access, but found the UM1725 description of the HAL drivers not enough. In the I2C section many potentially useful functions are barely explained. Can you point me to better ressources?
Thanks,
Patrick
2017-07-17 09:38 AM
Your STM32F4 may have up to 3 I2C peripheral busses. I2C1, I2C2, I2C3 for example. As a naming convention, in the HAL code, they would be hi2c1, hi2c2, hi2c3. Each I2C bus can have as many slaves as your address space and pull-up resistors allow
This is how I do it, but I'm just a hobbyist not a pro.
For this discussion, let us say the I2C address is 'dev_addr'. First thing I do is make sure the device will answer
while (HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t)(dev_addr<<1), 3, 100) != HAL_OK) { }
Ok then, if we get past that, we can try to read a register
HAL_StatusTypeDef status = HAL_OK;
uint8_t array[24] = {0};
status = HAL_I2C_Mem_Read_IT(&hi2c1, // i2c handle
(uint8_t)(dev_addr<<1), // i2c address, left aligned
(uint8_t)reg_addr, // register address on the slave i want to read
I2C_MEMADD_SIZE_8BIT, // random device uses 8bit register addresses. eeprom uses 16bit usually
(uint8_t*)(&array), // write returned data to this variable named array
cnt); // how many bytes to expect returned
if (status != HAL_OK)
{
switch (status)
{
case HAL_ERROR: do error stuff; break;
case HAL_BUSY: do busy stuff; break;
case HAL_TIMEOUT: do timeout stuff; break;
}
}
and dont forget to add the callback
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if (hi2c->Instance = I2C1)
{
// do stuff when the transfer on hi2c1 is complete
}
}
2017-07-17 10:22 AM
hello again !
By its nature every I2C transaction cannot be interrupted until finish, or else it will not be completed. (There is one bus and in your case, one master) If you are able to synchronize the transactions between threads without interruptions then, its ok.
HAL_I2C functions have return values of type HAL_StatusTypeDef. OK, ERROR, BUSY, TIMEOUT are returning values for your use.
Methods of managing an ic2 bus may include periodic transactions and hardware interrupts initiated from devices.
In my opinion, the best way to learn about the HAL functions is to analyze each function you want to learn (c file) spending probably a lot of time.
2017-07-17 12:25 PM
>Can you point me to better ressources?
STM32Cube_FW_F4_V1.16.0/Drivers/STM32F4xx_HAL_Driver/Inc/stm32f4xx_hal_i2c.h and stm32f4xx_hal_i2c_ex.h and corresponding .c files in Src
STM32Cube_FW_F4_V1.16.0/Projects/STM32446E-Nucleo/Examples/I2C/ or whatever your board is
2017-07-18 02:54 AM
Hi,
thanks for your input. I will dig a little more into HAL source code and see how to synchronize my processes.
Thanks,
Patrick