cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F072 I2C slave Receive callback

chandan bhatia
Associate II

Hello, I am using STM32F072. I want to use device in I2C slave and using HAL driver. I am looking to get callback when complete data is received at I2C slave side. I found function HAL_I2C_Slave_Receive_IT() which is kinda similar but here I need to mention length of data. Data length from other (master) is variable so suppose if I set length to 10 and data from master is 9 callback wouldn't come. Any other HAL function which can be use full or should I write my own driver level code.

9 REPLIES 9
KnarfB
Principal III

Hi,

you can receive/transmit byte by byte like this:

// emulated I2C „memory“
static uint8_t ram[256];
static uint8_t offset; // index of current RAM cell
static uint8_t first=1;// first byte --> new offset
 
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{
  first = 1;
  HAL_I2C_EnableListen_IT(hi2c); // slave is ready again
}
 
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
  if( TransferDirection==I2C_DIRECTION_TRANSMIT ) {
    if( first ) {
      HAL_I2C_Slave_Seq_Receive_IT(hi2c, &offset, 1, I2C_NEXT_FRAME);
    } else {
      HAL_I2C_Slave_Seq_Receive_IT(hi2c, &ram[offset], 1, I2C_NEXT_FRAME);
    }
  } else {
    HAL_I2C_Slave_Seq_Transmit_IT(hi2c, &ram[offset], 1, I2C_NEXT_FRAME);
  }
}
 
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
  if(first) {
    first = 0;
  } else {
    offset++;
  }
  HAL_I2C_Slave_Seq_Receive_IT(hi2c, &ram[offset], 1, I2C_NEXT_FRAME);
}
 
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
  offset++;
  HAL_I2C_Slave_Seq_Transmit_IT(hi2c, &ram[offset], 1, I2C_NEXT_FRAME);
}
 
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
  if( HAL_I2C_GetError(hi2c)==HAL_I2C_ERROR_AF ) {
    offset--; // transaction terminated by master
  } else {
  }
}

Tested on STM32F401RE Nucleo board.

hth

Frank

Thanks but byte by byte will make STM inefficient. I am planning to send like 30 data length so with this cpu needs to wakeup 30 times. I am looking to do in 1 time interrupt.

Also please let me know the use of HAL_I2C_Slave_Seq_Receive_IT ( ) function.

KnarfB
Principal III

The _Seq_ functions do not neccesarily generate start/stop conditions on the bus (depending on the flags used). Therefore you can build up one I2C bus transaction from several _Seq_ function calls.

Also can you tell for i2c slave transmit? I was looking for callback when master request for read data but i didn't find any such call back.

KnarfB
Principal III

The transfer direction is announced in HAL_I2C_AddrCallback (TransferDirection): the very first byte of a transfer after (re-)start consists of the 7-bit slave address plus a R/W bit. After that, the slave answers with HAL_I2C_Slave_Seq_Receive_IT resp. HAL_I2C_Slave_Seq_Transmit_IT as requested by the master.

hth

Frank

arthhh
Associate II

Hey!

I'm going through a similar problem...

Did you got it to work?

TDJ
Senior III

After HAL_I2C_Slave_Seq_Transmit_IT() is called within HAL_I2C_AddrCallback() upon transmit request I receive HAL_I2C_ERROR_OVR error in HAL_I2C_ErrorCallback(), communication stops and reset is required.

Tested with STM32L041 and the latest HAL STM32Cube_FW_L0_V1.12.1.

Receiving data works OK.

Any ideas?

related post: I2C Slave - clock stretching disables communication and other problems (STM32L0)

TDJ
Senior III

Here is another problem someone trying to implement this approach may encounter: STM32 I2C Slave mode HAL bug

The problem occurs with new I2C architecture - STM32F401RE uses 'old' architecture.

The bug has been registered here

https://github.com/STMicroelectronics/stm32l0xx_hal_driver/issues/5