Author Topic: I2C slave not working properly in STM32  (Read 635 times)

0 Members and 1 Guest are viewing this topic.

Offline BorisRapTopic starter

  • Contributor
  • Posts: 37
  • Country: de
I2C slave not working properly in STM32
« on: November 14, 2022, 09:47:32 am »
Hello, I'm trying to do a simple I2C slave device with a STM32F030C6T6. The idea is just to read and write some registers.

I'm doing it with
Code: [Select]
HAL_I2C_EnableListen_IT(&hi2c1);because I had problems in the past using
Code: [Select]
HAL_I2C_Slave_Receive_IT(hi2c, pData, Size);and
Code: [Select]
HAL_I2C_Slave_Transmit_IT(hi2c, pData, Size);at the same time.

In the protocol I "designed" to communicate with this device you do a write to indicate what register you want to access and then you do a read or a write depending on if you want to read it or write it.
So after the first write I have to expect both a read and a write.

I read a few tutorials and I came up with this:

Code: [Select]
#include "main.h"

I2C_HandleTypeDef hi2c1;

uint8_t txc  =0;
uint8_t i2cd1 = 88;

int main(void)
{
    SystemClock_Config();
    MX_GPIO_Init();
    MX_I2C1_Init();

    HAL_I2C_EnableListen_IT(&hi2c1);
    while(1)
    {
    HAL_Delay(10);
  if(txc == 1)
  {
  txc = 0;
  HAL_I2C_EnableListen_IT(&hi2c1);
  }   
    }
}

static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.Timing = 0x2000090E;
  hi2c1.Init.OwnAddress1 = 78;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
txc = 1;
}

void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
txc = 1;
}

void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
if(AddrMatchCode == 78)
{
if(TransferDirection == I2C_DIRECTION_RECEIVE)
{
//READ
HAL_I2C_Slave_Seq_Transmit_IT(&hi2c1, &i2cd1, 1, I2C_FIRST_AND_LAST_FRAME);
}
else if(TransferDirection == I2C_DIRECTION_TRANSMIT)
{
//WRITE
HAL_I2C_Slave_Seq_Receive_IT(&hi2c1, &i2cd1, 1, I2C_LAST_FRAME);
}
}
}

void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{
//HAL_I2C_EnableListen_IT(&hi2c1);
}


void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
HAL_I2C_Init(&hi2c1);
HAL_I2C_EnableListen_IT(&hi2c1);
HAL_GPIO_WritePin(OUT_LLC_EN_GPIO_Port, OUT_LED_Pin, 1);
}


(Some code has been excluded for simplicity)


I'm using a MCP2221 usb to I2C adapter to send the messages from c# code in my computer.
I'm also using a ISO1541DR I2C isolator.

The hardware is very simple, just the uC with the SDA and SCL connected to the ISO. Everything correctly decoupled and 4.7k pullups in bith SDA and SCL both sides of the ISO.

The receiving part works perfectly. I can send data from the computer to the STM it's received correctly and the STM starts another listing cycle, everything perfect.

When I'm trying to execute a read on the STM it doesn't work. The computer returns error code 0 (ok), the data I receive on the computer is always 255 and the led turns on (meaning the ErrorCalback function is executed).

Edit
I looked at the error code after the ErrorCallback execution and it is error code 8 (Overrun error)


While debugging, HAL_I2C_Slave_Seq_Transmit_IT(&hi2c1, &i2cd1, 1, I2C_FIRST_AND_LAST_FRAME); this line is executed with error code 0 and then it just fails.


Additional info:

I've been copying the methods of some tutorials, but I realized that in my system I have to put Clock No Stretch Mode to Enabled for it to work (at least the receiving part) if I set it to Disabled It doesn't work at all

Full disclaimer: I don't know very well what I'm doing.

I leave some images of CcubeIDE configuration.

Thank you!


Update

I read that Overrun can only occur when clock stretching is disabled. So I removed the ISO1541DR and enabled clock stretching and now it works just fine.

There is some problem when clock stretching is on and I'm using the ISO simultaneously.
« Last Edit: November 14, 2022, 10:35:06 am by BorisRap »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf