Skip to main content
Visitor II
January 23, 2021
Question

I2C doesn't work after uploading (only sometimes)

  • January 23, 2021
  • 12 replies
  • 2770 views

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 :)

    This topic has been closed for replies.

    12 replies

    Graduate II
    January 23, 2021

    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

    SenaxAuthor
    Visitor II
    January 23, 2021

    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.

    Graduate II
    January 23, 2021

    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.

    SenaxAuthor
    Visitor II
    January 23, 2021

    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?

    Graduate II
    January 23, 2021

    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

    SenaxAuthor
    Visitor II
    January 23, 2021

    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...

    SenaxAuthor
    Visitor II
    January 23, 2021

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

    0693W000007CQKsQAO.pngError 3 but expected result...

    Graduate II
    January 23, 2021

    Does HAL_I2C_Master_Transmit() report an error?

    SenaxAuthor
    Visitor II
    January 23, 2021

    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?

    SenaxAuthor
    Visitor II
    January 23, 2021

    So I also tried to use the sensor on an Arduino UNO, what just worked fine. I could upload the program a thousand times, and it worked every time.

    SenaxAuthor
    Visitor II
    January 23, 2021

    So this sounds interesting: when the MPU-6050 is connected to the board, I2C works fine, but as soon as I plug the other I2C Sensor in it stops working. Is it possible that one sensor blocks the other one?

    SenaxAuthor
    Visitor II
    January 23, 2021

    So I think I may have found the cause of the problem (please correct me if I'm wrong):

    My I2C Logic is 5v and all of my sensors are connected through the same 5v. So according to the data sheet the minimum resistance must be 1.53 kΩ for it to work.

    HMC 5983 Resistance: 1.57 kΩ

    MPU-6050 Resistance: 1.85 kΩ

    But as soon as I connect them together the Resistance drops to around 1.45 kΩ

    I will try to build a pull-up resistor into the circuit.