Skip to main content
chandan bhatia
Associate II
August 16, 2019
Question

STM32F072 I2C slave Receive callback

  • August 16, 2019
  • 9 replies
  • 4664 views

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.

This topic has been closed for replies.

9 replies

KnarfB
Super User
August 16, 2019

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

chandan bhatia
Associate II
August 17, 2019

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.

KnarfB
Super User
August 19, 2019

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.

chandan bhatia
Associate II
August 19, 2019

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
Super User
August 19, 2019

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
May 26, 2020

Hey!

I'm going through a similar problem...

Did you got it to work?

TDJ
Senior III
August 7, 2021

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
September 20, 2021

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