Skip to main content
AlexanderKibarov
Associate III
July 31, 2024
Solved

STM32 I2C Not Working with Other Interrupts

  • July 31, 2024
  • 29 replies
  • 6562 views

Hello, I'm using the STM32F413ZH board to read data from the MPU6050. While the data retrieval works when I implement it in a blank project, it fails to function correctly in my current project. This project also includes two additional UART interrupts, though they are not currently connected to the system. What might be causing the issue?

In this project, HAL_StatusTypeDef always returns HAL_BUSY

Thank You.

 

 

#include "main.h"
#include "string.h"

#define MAX_NMEA_PROTOCOL_CHARACTER_LENGTH_ 82

I2C_HandleTypeDef hi2c1;

UART_HandleTypeDef huart4;
UART_HandleTypeDef huart5;
UART_HandleTypeDef huart3;

PCD_HandleTypeDef hpcd_USB_OTG_FS;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART3_UART_Init(void);
static void MX_USB_OTG_FS_PCD_Init(void);
static void MX_UART4_Init(void);
static void MX_UART5_Init(void);
static void MX_I2C1_Init(void);

HAL_StatusTypeDef hal_status_one; //THIS CODE FOR I2C 
uint8_t data_mpu[1] = {0x00}; //THIS CODE FOR I2C 

struct Data_Struct {
	uint8_t leds_mode;
	uint8_t windows_angle;
	uint8_t turn_home;
	uint8_t tilt_protect;
	uint8_t turn_capsize;
} KIBAR_DATA;

uint8_t last_data[3] = { 255, 255, 255 };
uint8_t private_array[1];
uint8_t template_buffer[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00 };
uint8_t instruction_buffer[2] = { 0x00, 0x00 };
uint8_t main_buffer[5] = { 0x00, 0x00, 0x00, 0x00, 0x00 };
volatile uint8_t ff_index = 0;
volatile uint8_t array_index = 0;
volatile uint8_t is_there_back = 0;

volatile uint8_t gps_counter = 0;
volatile uint8_t mode_register = 0;
uint8_t private_gps_buffer[1] = { 0x00 };
uint8_t template_gps_buffer[MAX_NMEA_PROTOCOL_CHARACTER_LENGTH_];
uint8_t latitude_gps_buffer[9];
uint8_t longitude_gps_buffer[10];

//Uart NVIC Interrupt(Uart Global Interrupt) Aktif Edilmeli
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
	if (huart == &huart4) {
		HAL_UART_Receive_IT(&huart4, private_array, 1);
		if (private_array[0] == 255) {
			ff_index++;
			if (ff_index == 3) {
				if (array_index == 2) {
					for (int i = 0; i < 2; i++) {
						instruction_buffer[i] = template_buffer[i];
					}
					is_there_back = 1;
				} else if (array_index == 5) {
					for (int i = 0; i < 5; i++) {
						main_buffer[i] = template_buffer[i];
					}
					if (is_there_back == 1) {
						if (instruction_buffer[1] == 108) {
							KIBAR_DATA.leds_mode = main_buffer[1];
						}
						if (instruction_buffer[1] == 119) {
							KIBAR_DATA.windows_angle = main_buffer[1];
						}
						if (instruction_buffer[1] == 104) {
							if (KIBAR_DATA.turn_home == 0)
								KIBAR_DATA.turn_home = 1;
							else
								KIBAR_DATA.turn_home = 0;
						}
						if (instruction_buffer[1] == 116) {
							KIBAR_DATA.tilt_protect = main_buffer[1];
						}
						if (instruction_buffer[1] == 99) {
							if (KIBAR_DATA.turn_capsize == 0)
								KIBAR_DATA.turn_capsize = 1;
							else
								KIBAR_DATA.turn_capsize = 0;
						}
						is_there_back = 0;
					}
				}
				memset(template_buffer, 0x00, 12);
				ff_index = 0;
				array_index = 0;
			}
		} else {
			template_buffer[array_index] = private_array[0];
			array_index++;
		}
	}

	if (huart == &huart5) {
		HAL_UART_Receive_IT(&huart5, private_gps_buffer, 1);
		if (gps_counter == 0 && mode_register == 0
				&& private_gps_buffer[0] == 0x24)
			mode_register = 1;
		if (gps_counter == 0 && mode_register == 0
				&& private_gps_buffer[0] != 0x24)
			mode_register = 2;
		if (mode_register == 1) {
			if (private_gps_buffer[0] == 0x0A) {
				template_gps_buffer[gps_counter] = private_gps_buffer[0];
				if (gps_counter > 30) {
					for (int i = 7; i < 17; i++) {
						if (i != 11) {
							latitude_gps_buffer[i - 7] = template_gps_buffer[i];
						} else continue;
					}
					for (int i = 20; i < 31; i++) {
						if (i != 25) {
							longitude_gps_buffer[i - 20] = template_gps_buffer[i];
						} else continue;
					}
				}
				memset(template_gps_buffer, 0x00, MAX_NMEA_PROTOCOL_CHARACTER_LENGTH_);
				gps_counter = 0;
				mode_register = 0;
			} else {
				template_gps_buffer[gps_counter] = private_gps_buffer[0];
				gps_counter++;
				if (gps_counter == 5) {
					if (!(private_gps_buffer[0] == 0x4C)) {
						memset(template_gps_buffer, 0x00, MAX_NMEA_PROTOCOL_CHARACTER_LENGTH_);
						gps_counter = 0;
						mode_register = 2;
					}
				}
			}
		} else if (mode_register == 2) {
			if (private_gps_buffer[0] == 0x24) {
				template_gps_buffer[gps_counter] = private_gps_buffer[0];
				gps_counter++;
				mode_register = 1;
			}
		}
	}
}

int main(void)
{
 memset(template_gps_buffer, 0x00, MAX_NMEA_PROTOCOL_CHARACTER_LENGTH_);
 memset(latitude_gps_buffer, 0x00, 9);
 memset(longitude_gps_buffer, 0x00, 10);
 KIBAR_DATA.turn_capsize = 0;
 KIBAR_DATA.turn_home = 0;

 HAL_Init();

 SystemClock_Config();

 MX_GPIO_Init();
 MX_USART3_UART_Init();
 MX_USB_OTG_FS_PCD_Init();
 MX_UART4_Init();
 MX_UART5_Init();
 MX_I2C1_Init();

 HAL_UART_Receive_IT(&huart4, private_array, 1);
 HAL_UART_Receive_IT(&huart5, private_gps_buffer, 1);

 while (1) {
 //THIS CODE FOR I2C 
 hal_status_one = HAL_I2C_Mem_Read(&hi2c1, 0xD0, 0x75, 1, data_mpu, 1, 100);
	}
}


static void MX_I2C1_Init(void)
{
 hi2c1.Instance = I2C1;
 hi2c1.Init.ClockSpeed = 100000;
 hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
 hi2c1.Init.OwnAddress1 = 0;
 hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
 hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
 hi2c1.Init.OwnAddress2 = 0;
 hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
 hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
 if (HAL_I2C_Init(&hi2c1) != HAL_OK)
 {
 Error_Handler();
 }
}

static void MX_UART4_Init(void)
{
 huart4.Instance = UART4;
 huart4.Init.BaudRate = 9600;
 huart4.Init.WordLength = UART_WORDLENGTH_8B;
 huart4.Init.StopBits = UART_STOPBITS_1;
 huart4.Init.Parity = UART_PARITY_NONE;
 huart4.Init.Mode = UART_MODE_TX_RX;
 huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
 huart4.Init.OverSampling = UART_OVERSAMPLING_16;
 if (HAL_UART_Init(&huart4) != HAL_OK)
 {
 Error_Handler();
 }
}

static void MX_UART5_Init(void)
{
 huart5.Instance = UART5;
 huart5.Init.BaudRate = 115200;
 huart5.Init.WordLength = UART_WORDLENGTH_8B;
 huart5.Init.StopBits = UART_STOPBITS_1;
 huart5.Init.Parity = UART_PARITY_NONE;
 huart5.Init.Mode = UART_MODE_TX_RX;
 huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE;
 huart5.Init.OverSampling = UART_OVERSAMPLING_16;
 if (HAL_UART_Init(&huart5) != HAL_OK)
 {
 Error_Handler();
 }
}

static void MX_GPIO_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStruct = {0};

 __HAL_RCC_GPIOC_CLK_ENABLE();
 __HAL_RCC_GPIOH_CLK_ENABLE();
 __HAL_RCC_GPIOA_CLK_ENABLE();
 __HAL_RCC_GPIOB_CLK_ENABLE();
 __HAL_RCC_GPIOD_CLK_ENABLE();
 __HAL_RCC_GPIOG_CLK_ENABLE();

 HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD3_Pin|LD2_Pin, GPIO_PIN_RESET);

 HAL_GPIO_WritePin(USB_PowerSwitchOn_GPIO_Port, USB_PowerSwitchOn_Pin, GPIO_PIN_RESET);

 GPIO_InitStruct.Pin = USER_Btn_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(USER_Btn_GPIO_Port, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = LD1_Pin|LD3_Pin|LD2_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = USB_PowerSwitchOn_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(USB_PowerSwitchOn_GPIO_Port, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = USB_OverCurrent_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(USB_OverCurrent_GPIO_Port, &GPIO_InitStruct);
}

 

 

 

 

 

 

 

 

This topic has been closed for replies.
Best answer by Andrew Neil

@AlexanderKibarov wrote:

It was fixed when I switched i2c from 1st to 2nd but i dont know why


You mean you used I2C2 instead of I2C1 ?

Again,  observe what's happening on the I2C lines - what's different ?

As @TDK said, the HAL_BUSY return likely means that one/both line is being held low.

Look at the I2C lines to see if that is, indeed, the case with I2C1 but not I2C2.

If it is the case, then look at the schematic to see why that might be ...

29 replies

Andrew Neil
Super User
July 31, 2024

@AlexanderKibarov wrote:

it fails to function correctly in my current project.


What does that mean? What, exactly, is failing?

What investigation / testing / debugging have you done to find what's going on? What did you discover?

https://community.st.com/t5/community-guidelines/how-to-write-your-question-to-maximize-your-chances-to-find-a/ta-p/575228

 

PS

That's a huuuuuge amount of code within your UART interrupt handler - seldom a good idea!

 

What's going on here:

 

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
	if (huart == &huart4) {
		HAL_UART_Receive_IT(&huart4, private_array, 1);
		if (private_array[0] == 255) {
 :
 :

 

You realise that  HAL_UART_Receive_IT returns immediately; it does not wait until your buffer has been filled - or even received anything at all.

 

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
AlexanderKibarov
Associate III
July 31, 2024

As i wrote: In this project, HAL_StatusTypeDef always returns HAL_BUSY but when I open an empty project and write the same i2c codes it works fine.

Andrew Neil
Super User
July 31, 2024

@AlexanderKibarov wrote:

 HAL_StatusTypeDef always returns HAL_BUSY 


As the name suggests, HAL_StatusTypeDef is just a typedef - it cannot "return" anything.

You mean that  HAL_I2C_Mem_Read() returns  HAL_BUSY ?

So try stepping into HAL_I2C_Mem_Read(), and see why it returns  HAL_BUSY 

Also, check the states of your I2C lines - are they valid?

Are you sure you haven't introduced any conflicts when adding the UARTs?

 

See also the PS in my previous post

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
Andrew Neil
Super User
July 31, 2024

Not that it should matter, but what's the point of declaring single-element arrays??

uint8_t private_array[1];

 

uint8_t private_gps_buffer[1] = { 0x00 };

:thinking_face:

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
AlexanderKibarov
Associate III
July 31, 2024

Hello, I removed all the parts related to the uart for you, but I still continue to get HAL_BUSY.

 

#include "main.h"

I2C_HandleTypeDef hi2c1;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART3_UART_Init(void);
static void MX_USB_OTG_FS_PCD_Init(void);
static void MX_I2C1_Init(void);

HAL_StatusTypeDef hal_status_one;
uint8_t data_mpu[1] = {0x00};

int main(void)
{
 HAL_Init();

 SystemClock_Config();

 MX_GPIO_Init();
 MX_USART3_UART_Init();
 MX_USB_OTG_FS_PCD_Init();
 MX_I2C1_Init();
	while (1) {
		hal_status_one = HAL_I2C_Mem_Read(&hi2c1, 0xD0, 0x75, 1, data_mpu, 1, 100);
	}
}

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_SCALE1);

 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
 RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
 RCC_OscInitStruct.PLL.PLLM = 8;
 RCC_OscInitStruct.PLL.PLLN = 384;
 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
 RCC_OscInitStruct.PLL.PLLQ = 8;
 RCC_OscInitStruct.PLL.PLLR = 2;
 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_PLLCLK;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
 {
 Error_Handler();
 }
}

static void MX_I2C1_Init(void)
{
 hi2c1.Instance = I2C1;
 hi2c1.Init.ClockSpeed = 100000;
 hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
 hi2c1.Init.OwnAddress1 = 0;
 hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
 hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
 hi2c1.Init.OwnAddress2 = 0;
 hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
 hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
 if (HAL_I2C_Init(&hi2c1) != HAL_OK)
 {
 Error_Handler();
 }
}

static void MX_GPIO_Init(void)
{
 __HAL_RCC_GPIOC_CLK_ENABLE();
 __HAL_RCC_GPIOH_CLK_ENABLE();
 __HAL_RCC_GPIOB_CLK_ENABLE();
 __HAL_RCC_GPIOD_CLK_ENABLE();
 __HAL_RCC_GPIOG_CLK_ENABLE();
 __HAL_RCC_GPIOA_CLK_ENABLE();

 HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD3_Pin|LD2_Pin, GPIO_PIN_RESET);

 HAL_GPIO_WritePin(USB_PowerSwitchOn_GPIO_Port, USB_PowerSwitchOn_Pin, GPIO_PIN_RESET);

 GPIO_InitStruct.Pin = USER_Btn_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(USER_Btn_GPIO_Port, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = LD1_Pin|LD3_Pin|LD2_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = USB_PowerSwitchOn_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 HAL_GPIO_Init(USB_PowerSwitchOn_GPIO_Port, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = USB_OverCurrent_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(USB_OverCurrent_GPIO_Port, &GPIO_InitStruct);

}

 

Andrew Neil
Super User
July 31, 2024

@AlexanderKibarov wrote:

I removed all the parts related to the uart interrupt


But you still have:

 MX_GPIO_Init();
 MX_USART3_UART_Init();
 MX_USB_OTG_FS_PCD_Init();
 MX_I2C1_Init();
 MX_UART4_Init();
 MX_UART5_Init();

That's an awful lot of stuff besides just the I2C !

Again, I would suggest that you proceed as follows:

  1. Go back to your simple project with just the I2C - nothing else
  2. If that works, then add just one UART, doing a simple, polled echo - no interrupts
  3. If that works, then add the other UART, also doing a simple, polled echo - no interrupts
  4. If that works, then convert just one UART to an interrupt-based echo
  5. If that works, then also convert the other UART to an interrupt-based echo

 

That should identify if there's any fundamental problem, or if the problem lies elsewhere in your original code.

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
TDK
July 31, 2024

Always ensure a call to HAL_I2C_IsDeviceReady returns HAL_OK before you do anything else on the bus with that device.

"If you feel a post has answered your question, please click ""Accept as Solution""."
AlexanderKibarov
Associate III
July 31, 2024

hello, HAL_BUSY is returning as a result

ST Technical Moderator
July 31, 2024

Hello @AlexanderKibarov,

You can start from the blink project that is working fie and add step by step the UART configuration. 

You can look to the datasheet, there are some GPIO pin that are shared between UART and I2C1.

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Saket_Om
Andrew Neil
Super User
August 1, 2024
A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
AlexanderKibarov
Associate III
August 1, 2024

:face_with_tears_of_joy: