2019-08-16 01:04 AM
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.
2019-08-16 01:48 PM
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
2019-08-17 12:02 AM
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.
2019-08-18 11:27 PM
Also please let me know the use of HAL_I2C_Slave_Seq_Receive_IT ( ) function.
2019-08-19 08:00 AM
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.
2019-08-19 09:18 AM
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.
2019-08-19 09:29 AM
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
2020-05-26 07:03 AM
Hey!
I'm going through a similar problem...
Did you got it to work?
2021-08-07 03:09 PM
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)
2021-09-20 09:36 AM
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