How to fix the I2C slave issue with STM32G070?
HAL_I2C_ListenCpltCallback, HAL_I2C_AddrCallback, HAL_I2C_SlaveRxCpltCallback, HAL_I2C_SlaveTxCpltCallback
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-03-20 12:57 AM
Hi,
I'm trying to setup a stm32g070kb (32pin) MCU as I2C slave by using CubeIDE.
I would like to create a code which will work same as I2C Eeprom, but when I ask the stm32 (with another MCU) to return me a register or registers value, the returned registers are shifted by 1 register.
On this picture I recorded the communication between I2C Eprom and STM32G070 slave.
The gap in the STM32 communication makes the request shift by 1 byte for the master MCU, the eeprom doesn't have the gap.
here is the code:
// emulated I2C RAM
static uint8_t my_i2c_ram[128];
static uint8_t my_i2c_offset; // index of current RAM cell
static uint8_t first=1; // first byte --> new my_i2c_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, &my_i2c_offset, 1, I2C_NEXT_FRAME);
}
else
{
HAL_I2C_Slave_Seq_Receive_IT(hi2c, &my_i2c_ram[my_i2c_offset], 1, I2C_NEXT_FRAME);
}
}
else
{
HAL_I2C_Slave_Seq_Transmit_IT(hi2c, &my_i2c_ram[my_i2c_offset], 1, I2C_NEXT_FRAME);
}
}
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if(first)
{
first = 0;
}
else
{
my_i2c_offset++;
}
HAL_I2C_Slave_Seq_Receive_IT(hi2c, &my_i2c_ram[my_i2c_offset], 1, I2C_NEXT_FRAME);
}
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
my_i2c_offset++;
HAL_I2C_Slave_Seq_Transmit_IT(hi2c, &my_i2c_ram[my_i2c_offset], 1, I2C_NEXT_FRAME);
}
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
if( HAL_I2C_GetError(hi2c)==HAL_I2C_ERROR_AF )
{
// transaction terminated by master
my_i2c_offset--;
}
else
{
myerror = HAL_I2C_GetError(hi2c) ;
}
}
and the CubeIDE settings:
- Labels:
-
EEPROM devices
-
I2C
-
STM32G0 Series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-03-20 3:03 AM
the clk long low time is "clock stretching" .
if you dont want, try setting "enable":
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-03-20 3:25 AM
Thanks AScha.3 for the quick respond, I have tried that and with disabled clock streching the master can't even detect the stm32 slaves address .
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-03-21 2:11 AM
so we know: the "gap" is needed clock-stretching , because slave quite slow responding.
and so this is no error.
if you get 1+ register number , your counting is wrong somewhere then. :)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-03-22 3:24 AM
I'm sure it's not my misscounting because (as I described it) I ask the STM32 in the same way as I ask the EEprom.
I use an arduino as a master I2C to ask two slaves, STM32 with address 0x48 and the EEprom with 0x50 address.
I use this library #include <Eeprom24C01_02.h>
and I use the example code to ask bytes from both eeprom and stm32.
i2ceeprom(0x50);
i2cSTM(0x48);
//-----------------------------------------
Serial.println("EE read lib bytes");delay(10);
const byte count = 30;
byte outputBytes[count] = { 0 };
i2ceeprom.readBytes(0, count, outputBytes);
// Print read bytes.
for (byte i = 0; i < count; i++)
{
Serial.write(outputBytes[i]);
Serial.print(" ");
}
//------------------------------------------------------------------
Serial.println("STM read lib bytes");delay(10);
const byte count = 30;
byte outputBytes[count] = { 0 };
i2cSTM.readBytes(0, count, outputBytes);
// Print read bytes.
for (byte i = 0; i < count; i++)
{
Serial.write(outputBytes[i]);
Serial.print(" ");
}
I wrote the same data to each slave:
! " # $ % & ' ( ) * + , - . / 0 1 2 3 1 9 9 7 8 9 : ; < = >
this is what I get from the STM32 and from the EEprom:
the fist byte always rubbish and the rest are shifted.
I'm usinf the same code to ask so I'm sure the problem is with the STM slave settings or the code I'm using in CubeIDE.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-03-22 11:32 AM
There seems to be two problems:
- Your master device doesn't understand the clock stretching.
- The HAL broken bloatware is too slow - at 64 MHz the 40 us means 2560 clock cycles.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-03-23 4:48 AM
thanks,
- when I enable clock stretching , I can write data succesfully to the stm32 but it answers incorrectly, when I checked it with the oscilloscope looked like the dataline polarity changed. ???
- the stm is running on 64mhz , are you suggesting delay for the master while stm answering?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-03-23 3:07 PM
I'm just stating the fact (40 us), which can be seen in your oscilloscope images. Also I suggest to stop clicking CubeMX and using a broken bloatware and instead develop a normal code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-03-24 1:39 AM
The first picture was taken with 16MHz here is a new picture with 64MHz.
The "gap" is much shorter but the behavior is still the same.
I added also another picture with clock stretching enabled, the data line stayed high instead of low.
The eeprom request is still perfect. I know cubemx has issues but if someone could help me to find which bit or flag I have to change or clear to make it work as eeprom, I would greatly appreciate it.
