cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_I2C_Transmit returns HAL_BUSY.

akoluacik
Senior

I am trying to write a code so that I measure temperature and humidity via HTU21D sensor. It uses I2C interface. In the datasheet:

The HTU21D(F) sensor requires a voltage supply between 1.5V and 3.6V. After power up, the device needs at most 15ms while SCK is high for reaching idle state (sleep mode), i.e to be ready accepting commands from the MCU. No command should be sent before that time. Soft reset is recommended at start.

According to this information, I formed the following function:

void HTU21D_SensorInit(void)
{
	uint8_t pData[] = {0xFE}; // SOFT_RESET
	if(HAL_I2C_Mem_Write(&hi2c2, (DEVICE_ADDRESS << 1), WRITE_REGISTER, 1, pData, 1, HAL_MAX_DELAY) != HAL_OK)
	{
		Error_Handler();
	}
//	HAL_UART_Transmit(&huart1, (uint8_t*)"Sensor initialized!\r\n", 21, 100); for debugging
	HAL_Delay(15);
}

And I invoke this function in main after MX_I2C2 is called.

This function works find and doesn't go into Error_Handler. In while(1) part of the main function, I invoke the following function:

void HTU21D_MeasureTemp(void)
{
	uint8_t pData[] = {0xE3};
    HAL_UART_Transmit(&huart1, (uint8_t *)output, strlen(output), 100);
	HAL_StatusTypeDef res = HAL_I2C_Master_Transmit(&hi2c2, (DEVICE_ADDRESS << 1), pData, 1, HAL_MAX_DELAY);
	sprintf(output, "Res:%d\r\n", res);
	HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100);
	uint8_t temp[2];
	uint16_t raw_temp;
	HAL_UART_Transmit(&huart1, (uint8_t*)"Before if\r\n", 9, 100);
	HAL_UART_Transmit(&huart1, (uint8_t *)output, strlen(output), 100);
	if (res == HAL_OK)
	{
		HAL_I2C_Master_Receive(&hi2c2, ((DEVICE_ADDRESS << 1) | 0x01), temp, 2, HAL_MAX_DELAY);
		raw_temp = ((temp[0] << 8) | temp[1]);
		sprintf(output, "raw temp:%d\r\n", raw_temp);
		HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100);
		g_temp = -46.85 + 175.72 * raw_temp / 65536;
		HAL_UART_Transmit(&huart1, (uint8_t*)"In if after calc\r\n", 15, 100);
	}
	else
	{
		uint32_t error = HAL_I2C_GetError(&hi2c2);
		sprintf(output, "Error code:%lu\r\n", error);
		HAL_UART_Transmit(&huart1, (uint8_t*)output, 20, 100);
		Error_Handler();
	}
}

Where device address is (0x40). For reading, purpose, I shift it to left by 1 bit apply or operation with 0x01, this is described in datasheet.

However, this code returns HAL_BUSY, and HAL_I2C_GetError returns 0x32, which is Timeout afaik.

More interesting thing is that, if I do not call HTU21D_Init function, I get temperature value twice. I mean, the loop iterates only twice, then get stuck in somewhere else. What is wrong with my code?

Note that I am using proteus. This results were not taken from real life.

My whole code is below(excluding the parts Cubemx created):

#include "main.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
 
#define		TEMP_MEASUREMENT	0xE3
#define		HUMI_MEASUREMENT	0xE5
#define		WRITE_REGISTER		0xE6
#define		READ_REGISTER		0xE7
#define		DEVICE_ADDRESS      0x40
I2C_HandleTypeDef hi2c2; 
UART_HandleTypeDef huart1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C2_Init(void);
static void MX_USART1_UART_Init(void);
 
void HTU21D_SensorInit(void);
void HTU21D_MeasureTemp(void);
 
float temp;
float humidity;
float g_temp;
float g_humidity;
char output[50];
 
int main(void)
{
 
  HAL_Init();
 
  SystemClock_Config();
  MX_GPIO_Init();
  MX_I2C2_Init();
  MX_USART1_UART_Init();
  HTU21D_SensorInit();
  while (1)
  {
	HTU21D_MeasureTemp();
	sprintf(output, "temp:%.2f\r\n", g_temp);
	HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100);
	HAL_Delay(10);
  }
}
 
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
   __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
 
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}
 
static void MX_I2C2_Init(void)
{
  hi2c2.Instance = I2C2;
  hi2c2.Init.ClockSpeed = 100000;
  hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c2.Init.OwnAddress1 = 0;
  hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c2.Init.OwnAddress2 = 0;
  hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c2) != HAL_OK)
  {
    Error_Handler();
  }
}
 
static void MX_USART1_UART_Init(void)
{
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
}
static void MX_GPIO_Init(void)
{
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
 
}
void HTU21D_SensorInit(void)
{
	uint8_t pData[] = {0xFE}; // SOFT_RESET
	if(HAL_I2C_Mem_Write(&hi2c2, (DEVICE_ADDRESS << 1), WRITE_REGISTER, 1, pData, 1, HAL_MAX_DELAY) != HAL_OK)
	{
		Error_Handler();
	}
	HAL_UART_Transmit(&huart1, (uint8_t*)"Sensor initialized!\r\n", 21, 100);
	HAL_Delay(15);
}
 
void HTU21D_MeasureTemp(void)
{
	uint8_t pData[] = {TEMP_MEASUREMENT};
    HAL_UART_Transmit(&huart1, (uint8_t *)output, strlen(output), 100);
	HAL_StatusTypeDef res = HAL_I2C_Master_Transmit(&hi2c2, (DEVICE_ADDRESS << 1), pData, 1, HAL_MAX_DELAY);
	sprintf(output, "Res:%d\r\n", res);
	HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100);
	uint8_t temp[2];
	uint16_t raw_temp;
	HAL_UART_Transmit(&huart1, (uint8_t*)"Before if\r\n", 9, 100);
	HAL_UART_Transmit(&huart1, (uint8_t *)output, strlen(output), 100);
	if (res == HAL_OK)
	{
		HAL_I2C_Master_Receive(&hi2c2, ((DEVICE_ADDRESS << 1) | 0x01), temp, 2, HAL_MAX_DELAY);
		raw_temp = ((temp[0] << 8) | temp[1]);
		sprintf(output, "raw temp:%d\r\n", raw_temp);
		HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100);
		g_temp = -46.85 + 175.72 * raw_temp / 65536;
		HAL_UART_Transmit(&huart1, (uint8_t*)"In if after calc\r\n", 15, 100);
	}
	else
	{
		uint32_t error = HAL_I2C_GetError(&hi2c2);
		sprintf(output, "Error code:%lu\r\n", error);
		HAL_UART_Transmit(&huart1, (uint8_t*)output, 20, 100);
		Error_Handler();
	}
}
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  HAL_UART_Transmit(&huart1, (uint8_t*)"Error Handler\r\n", 15, 100);
  while (1)
  {
  }
}

1 ACCEPTED SOLUTION

Accepted Solutions

Hello @Anıl Koluaçık​ ,

I recommend you use only this function : HAL_I2C_Mem_Write() :

This function is intended for the common scenario in which the master device wants to write to a specific memory location on a slave device. Most I2C sensors, for instance, contain configuration and command registers used to change settings and initiate measurements.

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);


_legacyfs_online_stmicro_images_0693W00000bhvjHQAQ.pngOr you can try with your own function.

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

View solution in original post

15 REPLIES 15
Foued_KH
ST Employee

Hello @Anıl Koluaçık​ ,

I suggest you to use easily this function for the Read of the temperature :

uint_8 temp[1]; 
HAL_I2C_Mem_Write(&hi2c2, (DEVICE_ADDRESS << 1), TEMP_MEASUREMENT, 1, temp, 1, HAL_MAX_DELAY);

Also, you can try :

void HTU21D_MeasureTemp(void)
{
	uint8_t pData[] = {TEMP_MEASUREMENT};
    HAL_UART_Transmit(&huart1, (uint8_t *)output, strlen(output), 100);
	sprintf(output, "Res:%d\r\n", res);
	HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100);
	uint8_t temp[2];
	uint16_t raw_temp;
	HAL_UART_Transmit(&huart1, (uint8_t*)"Before if\r\n", 9, 100);
	HAL_UART_Transmit(&huart1, (uint8_t *)output, strlen(output), 100);
 
	if ( HAL_I2C_Master_Transmit(&hi2c2, (DEVICE_ADDRESS << 1), pData, 1, HAL_MAX_DELAY) == HAL_OK)
  {
		HAL_I2C_Master_Receive(&hi2c2, ((DEVICE_ADDRESS << 1) | 0x01), temp, 2, HAL_MAX_DELAY);
		raw_temp = ((temp[0] << 8) | temp[1]);
		sprintf(output, "raw temp:%d\r\n", raw_temp);
		HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100);
		g_temp = -46.85 + 175.72 * raw_temp / 65536;
		HAL_UART_Transmit(&huart1, (uint8_t*)"In if after calc\r\n", 15, 100);
	
	else 
	{
		uint32_t error = HAL_I2C_GetError(&hi2c2);
		sprintf(output, "Error code:%lu\r\n", error);
		HAL_UART_Transmit(&huart1, (uint8_t*)output, 20, 100);
		Error_Handler();
       }
  }
 

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Thanks for your response,

However, I have some questions.

First of all, I modified my function according to your suggestion:

void HTU21D_MeasureTemp(void)
{
	uint16_t temp[2];
	uint16_t raw_temp;
	HAL_StatusTypeDef res = HAL_I2C_Mem_Write(&hi2c2, (DEVICE_ADDRESS << 1), TEMP_MEASUREMENT, 1, temp, 2, HAL_MAX_DELAY);
	if (res == HAL_OK)
	{
		res = HAL_I2C_Mem_Read(&hi2c2, (DEVICE_ADDRESS << 1) | 0x01, TEMP_MEASUREMENT, 1, temp, 2, 100);
		if (res == HAL_OK)
		{
			raw_temp = (temp[1] << 8) | temp[0];
			g_temp = -46.85 + 175.72 * raw_temp / 65536;
		}
		else
			HAL_UART_Transmit(&huart1, (uint8_t*)"Mem Read Failed!", 17, 100);
	}
	else
		HAL_UART_Transmit(&huart1, (uint8_t*)"Mem Write Failed!", 18, 100);
}

But what I got is Mem Write failed.

Secondly, after the "also you can try" sentence, you provided a function but I couldn't find any difference with my function. Am I missing anything? If so, I am so sorry with my mistakes and plased if you explain more clear.

Lastly, special thanks for your interests to my issue.

Karl Yamashita
Lead III

@Anıl Koluaçık​ You can't use HAL_I2C_Mem_Write because it needs a register and data but you're not writing data to the temperature register. Using HAL_I2C_Mem_Read would have been good but if you read over the datasheet it specifically states that you have to wait for the conversion to complete when you write 0xE3. At which time the SCK line is blocked. So that is why HAL is returning HAL_BUSY


_legacyfs_online_stmicro_images_0693W00000bhu43QAA.png 

This table indicates how long you have to wait before you can read the temperature data


_legacyfs_online_stmicro_images_0693W00000bhu5fQAA.png 

So...

For doing a soft reset you can use HAL_I2C_Master_Transmit, not HAL_I2C_Mem_Write because you're just writing a register value and not data value.

As for reading the temperature, you need to use HAL_I2C_Master_Transmit to send 0xE3, pause for the given conversion time or check HAL_I2C_GetState. The HTU21D will release the SCK line after the conversion is done. Then you can call HAL_I2C_Master_Receive to read 3 bytes (2 data bytes + checksum) from the temperature register..

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

Hello @Anıl Koluaçık​ ,

I recommend you use only this function : HAL_I2C_Mem_Write() :

This function is intended for the common scenario in which the master device wants to write to a specific memory location on a slave device. Most I2C sensors, for instance, contain configuration and command registers used to change settings and initiate measurements.

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);


_legacyfs_online_stmicro_images_0693W00000bhvjHQAQ.pngOr you can try with your own function.

Foued

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

uint8_t cmd[] = {0xE3};
HAL_StatusTypeDef res = HAL_I2C_Master_Transmit(&hi2c2, (DEVICE_ADDRESS << 1), cmd, 1, 100);
HAL_Delay(50);

I think this is what you meant, I sent 0xE3 command and wait for 50ms. But I still get the same result.

BTW, I didn't check the whole datasheet, or couldn't understand so I didn't realize I have to wait for a while for measuring process. Thanks for noticing. And also special thanks for your response and interest.

Karl Yamashita
Lead III

You need to post the complete source code. From what you've posted you don't check the HAL status. Then we don't know how you're reading the register value?

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.
Pavel A.
Evangelist III

@Anıl Koluaçık​ From the datasheet, this device has two I2C modes: with SCK stretching (so called "hold") and without (called "no hold"). Usually for STM32 as master, you want the "no hold" mode.

In that mode, the device won't respond to commands until the measurement is ready.

This allows working with other devices on same bus while HTU21D is busy with measurements.

So you can just try reading periodically until read succeeds (or call HAL_I2C_IsDeviceReady until success, then read).

This is the part that yields error, that's why I only sent this part. The whole code is below:

#include "main.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
 
/* USER CODE END Includes */
 
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define		TEMP_MEASUREMENT	0xE3
#define		HUMI_MEASUREMENT	0xE5
#define		WRITE_REGISTER		0xE6
#define		READ_REGISTER		0xE7
#define		DEVICE_ADDRESS      0x40
/* USER CODE END PD */
 
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c2;
 
UART_HandleTypeDef huart1;
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C2_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
void HTU21D_SensorInit(void);
void HTU21D_MeasureTemp(void);
/* USER CODE END PFP */
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
float temp;
float humidity;
float g_temp = 20.00f;
float g_humidity;
char output[50];
/* USER CODE END 0 */
 
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C2_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  HTU21D_SensorInit();
  /* USER CODE END 2 */
  HAL_UART_Transmit(&huart1, (uint8_t*)"After sensor init\r\n!", 19, 100);
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	 HAL_UART_Transmit(&huart1, (uint8_t*)"In while\r\n!", 10, 100);
	HTU21D_MeasureTemp();
	HAL_UART_Transmit(&huart1, (uint8_t*)"after func\r\n", 13, 100);
	sprintf(output, "temp:%.2f\r\n", g_temp); // prints 20.00 because g_temp value is initialized with 20.00
	HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100); 
	HAL_Delay(10);
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
 
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
 
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}
 
/**
  * @brief I2C2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C2_Init(void)
{
 
  /* USER CODE BEGIN I2C2_Init 0 */
 
  /* USER CODE END I2C2_Init 0 */
 
  /* USER CODE BEGIN I2C2_Init 1 */
 
  /* USER CODE END I2C2_Init 1 */
  hi2c2.Instance = I2C2;
  hi2c2.Init.ClockSpeed = 100000;
  hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c2.Init.OwnAddress1 = 0;
  hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c2.Init.OwnAddress2 = 0;
  hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C2_Init 2 */
 
  /* USER CODE END I2C2_Init 2 */
 
}
 
/**
  * @brief USART1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART1_UART_Init(void)
{
 
  /* USER CODE BEGIN USART1_Init 0 */
 
  /* USER CODE END USART1_Init 0 */
 
  /* USER CODE BEGIN USART1_Init 1 */
 
  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
 
  /* USER CODE END USART1_Init 2 */
 
}
 
/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
 
}
 
/* USER CODE BEGIN 4 */
void HTU21D_SensorInit(void)
{
	uint8_t pData[] = {0xFE}; // SOFT_RESET
	if(HAL_I2C_Master_Transmit(&hi2c2, (DEVICE_ADDRESS << 1), pData, 1, HAL_MAX_DELAY) != HAL_OK)
	{
		Error_Handler();
	}
	/*if(HAL_I2C_Mem_Write(&hi2c2, (DEVICE_ADDRESS << 1), WRITE_REGISTER, 1, pData, 1, HAL_MAX_DELAY) != HAL_OK)
	{
		Error_Handler();
	}*/
	HAL_Delay(15);
	HAL_UART_Transmit(&huart1, (uint8_t*)"Sensor initialized!\r\n", 21, 100); // prints Sensor initialized!
	HAL_StatusTypeDef is_ready = HAL_I2C_IsDeviceReady(&hi2c2, (DEVICE_ADDRESS << 1), 10, 100);
	sprintf(output, "is_ready:%d\r\n", is_ready);
	HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100); prints HAL_OK
	uint32_t error = HAL_I2C_GetError(&hi2c2);
	sprintf(output, "error:%lu\n\r", error);
	HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100);// prints 0, HAL_NO_ERROR
}
void HTU21D_MeasureTemp(void)
{
	uint8_t temp[3];
	uint8_t cmd[] = {TEMP_MEASUREMENT};
	uint16_t raw_temp;
	HAL_StatusTypeDef is_ready = HAL_I2C_IsDeviceReady(&hi2c2, (DEVICE_ADDRESS << 1), 10, 100); // returns HAL_OK
	HAL_StatusTypeDef res = HAL_I2C_Master_Transmit(&hi2c2, (DEVICE_ADDRESS << 1), cmd, 1, 100);
	HAL_Delay(100); // I tried different values
	sprintf(output, "res:%d\r\n", res);
	HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100); // returns HAL_ERROR
	HAL_StatusTypeDef is_ready = HAL_I2C_IsDeviceReady(&hi2c2, (DEVICE_ADDRESS << 1), 10, HAL_MAX_DELAY); // returns HAL_OK
	sprintf(output, "is_ready:%d\r\n", is_ready); // prints HAL_OK
	HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100);
	uint32_t error = HAL_I2C_GetError(&hi2c2); // returns 0, HAL_NO_ERROR,
	sprintf(output, "error:%lu\n\r", error);
	HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100); // prints 0, HAL_NO_ERROR
	if (res == HAL_OK)
	{
		res = HAL_I2C_Master_Receive(&hi2c2, (DEVICE_ADDRESS << 1) | 0x01, temp, 3, HAL_MAX_DELAY);
		if (res == HAL_OK)
		{
			raw_temp = (temp[1] << 8) | temp[0];
			g_temp = -46.85 + 175.72 * raw_temp / 65536;
		}
		else
			HAL_UART_Transmit(&huart1, (uint8_t*)"Receive Failed!\r\n", 17, 100);
	}
	else // THIS PART IS EXECUTED
	{
		HAL_UART_Transmit(&huart1, (uint8_t*)"Tx Failed!\r\n", 12, 100);
		uint32_t error = HAL_I2C_GetError(&hi2c2); // returns 0, HAL_NO_ERROR
		sprintf(output, "error:%lu\n\r", error);
		HAL_UART_Transmit(&huart1, (uint8_t*)output, strlen(output), 100); // prints 0, HAL_NO_ERROR
	}
}
/* USER CODE END 4 */
 
/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  HAL_UART_Transmit(&huart1, (uint8_t*)"Error Handler\r\n", 15, 100);
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}
 

One part that I still cannot understand is that, I researched somewhere else they realized that if there are more register in an I2C device, then we need to use HAL_I2C_Mem functions, however, if there is only one register, we can use HAL_I2C_Master functions. Is that true? And I couldnt understand my device if it has more memory registers? Because it is said, for instance,0xE3 is a command, not register. So I am using HAL_I2C_Master rather than mem functions. Is that OK?

I am so newbie for this concept. I am sorry if I have been persisting on my mistakes. They aren't on purpose.

I tried you suggestion sir, however the device is ready, I still get HAL_ERROR when transmitting 0xE3.