cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G071G8U6TR trying to use I2C communication

GTann.1
Associate II

I'm trying to use the I2C line of an STM32G071G8U6TR to talk with an external device. I've used the STMCube to configure the pins to be I2C with pull ups and high speed which created this Init

 

 

 

static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */
	//hi2c1.Init.Timing = I2C_SPEEDCLOCK;
	//hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_10BIT;
	//hi2c1.Init.OwnAddress2 = 0xff;
  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.Timing = 0x00503D58;
  hi2c1.Init.OwnAddress1 = 0;
  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 */
  if(HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }
  /* USER CODE END I2C1_Init 2 */

}

 

 

 

However when I try and use this code to send commands to the device the status return is always returned as HAL_I2C_STATE_RESET, I've used a scope to check both the I2C lines and they are both high when this code is called.

 

 

void connect_vane()
{
	//status = HAL_I2C_Master_Transmit_IT(&I2cHandle, MOTOR_ADDRESS_WRITE, (uint8_t*)aTxBuffer, TXBUFFERSIZE);
	//if (HAL_OK == status)
	//{
	      //bytes_written = bytes_to_write;
		  //connect_vane();

		  //message_buf[0] = 0x66;			//Address 66
		  /*message_buf[0] = 0x3C;			// '<'
		message_buf[1] = 0x30;			// '0'
		message_buf[2] = 0x31;			// '1'
		message_buf[3] = 0x3E;			// '>'
			message_buf[4] = 0x0D;			// '/r'*/
		  //HAL_I2C_Master_Transmit(&hi2c1, MOTOR_ADDRESS_WRITE, message_buf, 5, 1000);
		  aTxBuffer[0] = 0x66;
		  aTxBuffer[1] = 0x3C;			// '<'
		  aTxBuffer[2] = 0x30;			// '0'
		  aTxBuffer[3] = 0x31;			// '1'
		  aTxBuffer[4] = 0x3E;			// '>'
		  aTxBuffer[5] = 0x0D;			// '/r'

		  do
		  {
			  if(HAL_I2C_Master_Transmit(&I2cHandle, MOTOR_ADDRESS_WRITE, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 1000)!= HAL_OK)
			  {
				  /* Error_Handler() function is called when error occurs. */
				  Error_Handler();
			  }

	    /*##-3- Wait for the end of the transfer #################################*/
	    /*  Before starting a new communication transfer, you need to check the current
	        state of the peripheral; if it�s busy you need to wait for the end of current
	        transfer before starting a new one.
	        For simplicity reasons, this example is just waiting till the end of the
	        transfer, but application may perform other tasks while transfer operation
	        is ongoing. */
			  while (HAL_I2C_GetState(&I2cHandle) != HAL_I2C_STATE_READY)
			  {

			  }

	    /* When Acknowledge failure occurs (Slave don't acknowledge it's address)
	       Master restarts communication */
		  }
		  while(HAL_I2C_GetError(&I2cHandle) == HAL_I2C_ERROR_AF);

		  HAL_Delay(50);

		  do
		  {
			  if(HAL_I2C_Master_Receive(&I2cHandle, (uint16_t)MOTOR_ADDRESS_WRITE, (uint8_t *)aRxBuffer, RXBUFFERSIZE, 1000) != HAL_OK)
			  {
				  /* Error_Handler() function is called when error occurs. */
				  Error_Handler();
			  }


	    /*##-5- Wait for the end of the transfer #################################*/
	    /*  Before starting a new communication transfer, you need to check the current
	        state of the peripheral; if it�s busy you need to wait for the end of current
	        transfer before starting a new one.
	        For simplicity reasons, this example is just waiting till the end of the
	        transfer, but application may perform other tasks while transfer operation
	        is ongoing. */
			  while (HAL_I2C_GetState(&I2cHandle) != HAL_I2C_STATE_READY)
			  {

			  }

	    /* When Acknowledge failure occurs (Slave don't acknowledge it's address)
	       Master restarts communication */
		  }
		  while(HAL_I2C_GetError(&I2cHandle) == HAL_I2C_ERROR_AF);

}

 

 

 

9 REPLIES 9
Karl Yamashita
Lead III

Are you using internal or external pull-up resistors?

What I2C device? What slave address is MOTOR_ADDRESS_WRITE defined as? 

Do you see data activity?

 

Don't worry, I won't byte.
TimerCallback tutorial! | UART and DMA Idle tutorial!

If you find my solution useful, please click the Accept as Solution so others see the solution.
Ozone
Lead II

> I've used the STMCube to configure the pins to be I2C with pull ups ...

That will not work.
The internal pull-ups are an order of magnitude too weak. You need about 1k ... 5k externally.

I'm currently only using the STM32's internal pull up resistors.

 

The device is a New Scale M3-LS-U2-8.

 

MOTOR_ADDRESS_WRITE is defined as 66.

 

With the code above it gets to:

if(HAL_I2C_Master_Transmit(&I2cHandle, MOTOR_ADDRESS_WRITE, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 1000)!= HAL_OK)

and returns busy. When I have added in a check status line above and debugged in the status is reading as "HAL_I2C_STATE_RESET"


@GTann.1 wrote:

I'm currently only using the STM32's internal pull up resistors."


As @Ozone said, they are almost certainly too weak.

 


@GTann.1 wrote:

The device is a New Scale M3-LS-U2-8.


So one of these: https://www.newscaletech.com/micro-motion-modules/m3-ls-linear-smart-stages/ ?

https://www.newscaletech.com/wp-content/uploads/M3-LS-U2-datasheet.pdf

Always best to give a link - so that people know exactly what you're referring to.

 


@GTann.1 wrote:

I'm currently only using the STM32's internal pull up resistors.

 

The device is a New Scale M3-LS-U2-8.

 

MOTOR_ADDRESS_WRITE is defined as 66.

 

With the code above it gets to:

if(HAL_I2C_Master_Transmit(&I2cHandle, MOTOR_ADDRESS_WRITE, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 1000)!= HAL_OK)

and returns busy. When I have added in a check status line above and debugged in the status is reading as "HAL_I2C_STATE_RESET"


Do you mean 0x66 or decimal 66?

To me it sounds like the slave address is decimal 66 which is hex 0x42.

If it is, then you have to shift the 7-bit address to the left by 1 prior to calling the function. 

 

HAL_I2C_Master_Transmit(&I2cHandle, MOTOR_ADDRESS_WRITE << 1, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 1000)

 

 

Which is explained in the HAL_I2C_Master_Transmit driver

 

/**
  * @brief  Transmits in master mode an amount of data in blocking mode.
  * @PAram  hi2c Pointer to a I2C_HandleTypeDef structure that contains
  *                the configuration information for the specified I2C.
  * @PAram  DevAddress Target device address: The device 7 bits address value
  *         in datasheet must be shifted to the left before calling the interface
  * @PAram  pData Pointer to data buffer
  * @PAram  Size Amount of data to be sent
  * @PAram  Timeout Timeout duration
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
                                          uint16_t Size, uint32_t Timeout)
{
  uint32_t tickstart;
  uint32_t xfermode;

 

 

Also, you MUST use external pull-ups on the SDA and SCL lines, around 4.7K Ohms.

Don't worry, I won't byte.
TimerCallback tutorial! | UART and DMA Idle tutorial!

If you find my solution useful, please click the Accept as Solution so others see the solution.

Sorry, I will remember in future to include a link.

 

That is the correct device.

The defined address is 0x66, the actual device address is 0x33 so 0x66 is used as a shifted version of the address.

Sometimes the vendor provides "clues" in the documentation what he means with I2C address.
But those are defined as 7-bit in the standard, and are extended to 8-bit in practice with the R/W bit.

The trouble is now, does the spec talk about an actual 7-bit value (like e.g. with SMBus), or do they mean "extended to 8-bit with the R/W-bit masked out". I came across both.
Occasionally, only trial and error helps ...

Indeed, there is industry-wide confusion & inconsistency with I2C addresses.

Only last week:

https://community.st.com/t5/stm32-mcus-products/i2c-communication-between-stm32l4r5-and-esp32/m-p/767914/highlight/true#M272098

 

This is just one reason why it's vital to use an oscilloscope or analyser to see what's actually happening on the wires!