cancel
Showing results for 
Search instead for 
Did you mean: 

I2C doesn't work after uploading (only sometimes)

Senax
Associate II

I wrote a little program that reads I2C values with interrupts: The Problem is that sometimes it just doesn't work after uploading. I just have to run it so many times till it works (not changing anything in the code). It seems like its just coincidence if it works or not.

Here are the Details:

Sensor: HMC 5983 or MPU-6050 (same problem)

Board: STM32F103RB (Nucleo 64)

Code (without the generated Cubemx stuff):

int main(void) {
    /*/////////////////////Setup/////////////////////////*/
	buf[0] = 0x00;
	buf[1] = 0x78;
	buf[2] = 0x80;
	buf[3] = 0x00;
	HAL_I2C_Master_Transmit(&hi2c1, Kompass_ADDR, buf, 4, 100);
	/*//////////////////////Start of IT Routine//////////////////*/
	buf[0] = 0x03;
	HAL_I2C_Master_Transmit_IT(&hi2c1, Kompass_ADDR, buf, 1);
 
	/* USER CODE END 2 */
 
	/* Infinite loop */
	/* USER CODE BEGIN WHILE */
	while (1) {
		/*/////////////////////printing the value////////////////////////*/
	    sprintf((char*) Serial_buffer, " X %i \r\n", DataX);
		HAL_UART_Transmit(&huart2, (uint8_t*) Serial_buffer, strlen((char*) Serial_buffer), 100);
		HAL_Delay(500);
		/* USER CODE END WHILE */
 
		/* USER CODE BEGIN 3 */
	}
	/* USER CODE END 3 */
}
 
 
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) {
	HAL_I2C_Master_Receive_IT(&hi2c1, Kompass_ADDR, buf, 6);
}
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c) {
	DataX = ((int16_t) buf[0]) << 8 | buf[1];
	buf[0] = 0x03;
	HAL_I2C_Master_Transmit_IT(&hi2c1, Kompass_ADDR, buf, 1);
}
////////////////////////////I2C Init Function////////////////////////
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();
	}
}
 

Thank you in Advance 🙂

14 REPLIES 14

Check initialization of clocks, pins, peripheral.

Out of reset check if the I2C slave needs time to start, generally slower devices, often lacking a power-on-reset signal

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Senax
Associate II

I really appreciate your fast answer, but I don't really know how to check the initialization.

But I put some HAL_Delays into the setup process, what didn't help. I noticed that I don't even have to upload the program again, I just need to press the Reset button a couple of times until it works again.

Look in the MSP code (search HAL_GPIO_Init)

The STM32 F1 parts had particular ordering issues for I2C, check the status reported by the peripheral in the failing cases, check if it is busy.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Senax
Associate II

Ok I don't really understand what I need to do, I'm rather new to the stm32 World.

What exactly do you mean with MSP code? I searched a bit and found these four files:0693W000007CQHAQA4.pngInto which one should I look?

The stm32f1xx_hal_msp.c would be the source code where CubeMX is hiding the code, much of the stuff in main.c being mostly superficial.

The .O is an object file (compiled version), and the .D is a dependency file, these are GNU/GCC outputs, not STM32 specific.

The RM0008 is the Reference Manual for the F1, this describes the I2C Peripheral.

Print out I2C1->SR2

0693W000007CQIXQA4.jpghttps://www.st.com/resource/en/reference_manual/cd00171190-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Senax
Associate II

Ok, that's something I can understand. I put a little Code into my program that outputs the register every time Hal is not ok.

And interesting I have two cases of error:

In the first case the Output is wrong but not zero (something around 700) :

Error 3 = 0011 ⇾ This means busy and Master Mode

0693W000007CQKdQAO.pngIn the second case the Output stays zero:

Error 2 = 0010 → This means busy in Slave mode???

0693W000007CQKYQA4.pngSo now I'm confused...

Senax
Associate II

This still isn't confusing enough so here is another case:

0693W000007CQKsQAO.pngError 3 but expected result...

Does HAL_I2C_Master_Transmit() report an error?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Senax
Associate II

Oh sorry, one of those pictures didn't upload:

The code is implemented if Hal_ok isn't true:

0693W000007CQbAQAW.pngAre there any other possibilities to look if the function reports an error?