Author Topic: STM32F I2C Communication Fails  (Read 3491 times)

0 Members and 1 Guest are viewing this topic.

Offline EVblog1Topic starter

  • Regular Contributor
  • *
  • Posts: 145
  • Country: 00
STM32F I2C Communication Fails
« on: July 12, 2026, 10:28:39 am »
Hello Everyone

I am trying to establish I2C communication between an STM32F407G-DISC1 board and a DS1307 RTC. My first goal is simply to verify that the STM32 can detect the DS1307 by receiving an ACK from its I2C address before moving on to reading or writing any registers.

The hardware connections are:

PB6 connected to SCL (DS1307)
PB7 connected to SDA (DS1307)
5V board connected to VCC (DS1307)
Board GND connected to GND
4.7 kΩ pull-up resistor from SCL to 3V
4.7 kΩ pull-up resistor from SDA to 3.3V

I configured I2C1 in STM32CubeMX with the following settings:

I2C speed: 100 kHz
Addressing mode: 7-bit
STM32 configured as the I2C master


To check whether the DS1307 responds to its I2C address, I called:

HAL_I2C_IsDeviceReady(&hi2c1, (0x68 << 1), 3, 100);

I used the onboard LEDs to indicate the result:

Green LED DS1307 acknowledged its address)
Red LED, Any other return value (no ACK or I2C communication failed)

Every time I run the program, the red LED turns on

Code: [Select]
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2026 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_host.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

I2S_HandleTypeDef hi2s3;

SPI_HandleTypeDef hspi1;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
static void MX_I2S3_Init(void);
static void MX_SPI1_Init(void);
void MX_USB_HOST_Process(void);

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* 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_I2C1_Init();
  MX_I2S3_Init();
  MX_SPI1_Init();
  MX_USB_HOST_Init();
  /* USER CODE BEGIN 2 */
  HAL_StatusTypeDef status;

  status = HAL_I2C_IsDeviceReady(&hi2c1, (0x68 << 1), 3, 100);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    //MX_USB_HOST_Process();

    /* USER CODE BEGIN 3 */
  if (status == HAL_OK)
      {
          /* DS1307 acknowledged its address */
          HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);   // Green LED ON
      }
      else
      {
          /* DS1307 did not acknowledge */
          HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);   // Red LED ON
      }
  }
  /* 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_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  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_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

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

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  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();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief I2S3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2S3_Init(void)
{

  /* USER CODE BEGIN I2S3_Init 0 */

  /* USER CODE END I2S3_Init 0 */

  /* USER CODE BEGIN I2S3_Init 1 */

  /* USER CODE END I2S3_Init 1 */
  hi2s3.Instance = SPI3;
  hi2s3.Init.Mode = I2S_MODE_MASTER_TX;
  hi2s3.Init.Standard = I2S_STANDARD_PHILIPS;
  hi2s3.Init.DataFormat = I2S_DATAFORMAT_16B;
  hi2s3.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
  hi2s3.Init.AudioFreq = I2S_AUDIOFREQ_96K;
  hi2s3.Init.CPOL = I2S_CPOL_LOW;
  hi2s3.Init.ClockSource = I2S_CLOCK_PLL;
  hi2s3.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE;
  if (HAL_I2S_Init(&hi2s3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2S3_Init 2 */

  /* USER CODE END I2S3_Init 2 */

}

/**
  * @brief SPI1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

  /* USER CODE END SPI1_Init 0 */

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  /* USER CODE BEGIN MX_GPIO_Init_1 */

  /* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOE_CLK_ENABLE();
  __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();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(CS_I2C_SPI_GPIO_Port, CS_I2C_SPI_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(OTG_FS_PowerSwitchOn_GPIO_Port, OTG_FS_PowerSwitchOn_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOD, LD4_Pin|LD3_Pin|LD5_Pin|LD6_Pin
                          |Audio_RST_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : CS_I2C_SPI_Pin */
  GPIO_InitStruct.Pin = CS_I2C_SPI_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(CS_I2C_SPI_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : OTG_FS_PowerSwitchOn_Pin */
  GPIO_InitStruct.Pin = OTG_FS_PowerSwitchOn_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(OTG_FS_PowerSwitchOn_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : PDM_OUT_Pin */
  GPIO_InitStruct.Pin = PDM_OUT_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
  HAL_GPIO_Init(PDM_OUT_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : B1_Pin */
  GPIO_InitStruct.Pin = B1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : BOOT1_Pin */
  GPIO_InitStruct.Pin = BOOT1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(BOOT1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : CLK_IN_Pin */
  GPIO_InitStruct.Pin = CLK_IN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
  HAL_GPIO_Init(CLK_IN_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : LD4_Pin LD3_Pin LD5_Pin LD6_Pin
                           Audio_RST_Pin */
  GPIO_InitStruct.Pin = LD4_Pin|LD3_Pin|LD5_Pin|LD6_Pin
                          |Audio_RST_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  /*Configure GPIO pin : OTG_FS_OverCurrent_Pin */
  GPIO_InitStruct.Pin = OTG_FS_OverCurrent_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(OTG_FS_OverCurrent_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : MEMS_INT2_Pin */
  GPIO_InitStruct.Pin = MEMS_INT2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(MEMS_INT2_GPIO_Port, &GPIO_InitStruct);

  /* USER CODE BEGIN MX_GPIO_Init_2 */

  /* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* 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();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

To investigate further, I connected a logic analyzer to the I2C bus. Surprisingly, both SCL and SDA remain completely idle. There is no START condition, no clock pulses, and no data on either line when HAL_I2C_IsDeviceReady() is executed.

Because there is no activity on the bus at all, it appears that the STM32 is not attempting to generate any I2C transaction. This makes me suspect that the problem may be with the I2C peripheral configuration or initialization rather than with the DS1307 itself.

At this point, I'm not sure what to investigate next.

I have attached a screenshot of my hardware setup for reference.

 

Offline voltsandjolts

  • Supporter
  • ****
  • Posts: 3845
  • Country: gb
Re: STM32F I2C Communication Fails
« Reply #1 on: July 12, 2026, 11:16:20 am »
To investigate further, I connected a logic analyzer to the I2C bus. Surprisingly, both SCL and SDA remain completely idle. There is no START condition, no clock pulses, and no data on either line when HAL_I2C_IsDeviceReady() is executed.

Well done using the logic analyser, this shows you have initiative, you're learning how to methodically track down problems :-+

Quote
Because there is no activity on the bus at all, it appears that the STM32 is not attempting to generate any I2C transaction. This makes me suspect that the problem may be with the I2C peripheral configuration or initialization rather than with the DS1307 itself.

At this point, I'm not sure what to investigate next.

You're correct, it could well be a peripheral configuration issue. The best way you could benefit from this situation is by solving it yourself. That solves this problem, but then gives you confidence in tackling the next problems you will have - it actually sets you on the path to being a good firmware engineer.

My thoughts on your way forward;

Stop using the STMcube generator. The best way to learn is bare metal. Read the datasheets, setup registers as appropriate. It's quite a lot of reading (learning) but just a few dozen lines of code to get I2C running.

First of all, just toggle some IO pins. Then setup I2C and just send something, anything, you can see on the logic analyser.

Once you have done some simple bare metal code, feel free to go back to STMCube generator if you must. But now you have a deeper understanding of how to fix things. Rather than "code gen didn't work, let's ask eevblog forum" which is not a long term solution.

https://github.com/cpq/bare-metal-programming-guide
https://github.com/ataradov/mcu-starter-projects

 

Offline lichurbagan

  • Regular Contributor
  • *
  • Posts: 230
  • Country: bd
Re: STM32F I2C Communication Fails
« Reply #2 on: July 12, 2026, 12:39:35 pm »
Check if I2C1 clock is enabled

Inside HAL_I2C_MspInit() there should also be
__HAL_RCC_I2C1_CLK_ENABLE();
Without the peripheral clock, the I2C peripheral cannot run.
 

Offline AVI-crak

  • Regular Contributor
  • *
  • Posts: 151
  • Country: ru
    • Rtos
Re: STM32F I2C Communication Fails
« Reply #3 on: July 12, 2026, 01:48:19 pm »
HAL функции всегда возвращают номер ошибки.
 

Online squadchannel

  • Super Contributor
  • ***
  • Posts: 1273
  • Country: jp
  • deepl translate user
Re: STM32F I2C Communication Fails
« Reply #4 on: July 12, 2026, 02:02:21 pm »
I used the onboard LEDs to indicate the result:

Green LED DS1307 acknowledged its address)
Red LED, Any other return value (no ACK or I2C communication failed)

Every time I run the program, the red LED turns on

no need to do that. Just step through the code in debug mode to check whether each register is set correctly.
That’s a method used with older microcontrollers. I do it occasionally myself, but gdb will tell you everything you need to know.

All you need to know is whether the registers are set correctly.
Check the clock settings.
whether the clocks for the I/O and I2C peripherals are set correctly.
whether the PLL settings are correct.
whether the supplied clock is within the specified range.
whether the I/O is set to alternate mode (for I2C?).

They say HAL wraps everything up and makes it simple, but considering all these factors, I find it a hassle. :box:

Setting up the clock is a hassle, but you can manage it with a screenshot of the clock tree and mspaint.exe.
« Last Edit: July 12, 2026, 02:04:38 pm by squadchannel »
 

Offline voltsandjolts

  • Supporter
  • ****
  • Posts: 3845
  • Country: gb
Re: STM32F I2C Communication Fails
« Reply #5 on: July 12, 2026, 04:29:03 pm »
HAL функции всегда возвращают номер ошибки.
Translation:
HAL functions always return an error code.
 

Offline HwAoRrDk

  • Super Contributor
  • ***
  • Posts: 1931
  • Country: gb
Re: STM32F I2C Communication Fails
« Reply #6 on: July 12, 2026, 07:42:48 pm »
It doesn't appear as though you're configuring the I2C GPIO pins for Alternate Function mode.

Code: [Select]
  /*Configure GPIO pin : CS_I2C_SPI_Pin */
  GPIO_InitStruct.Pin = CS_I2C_SPI_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(CS_I2C_SPI_GPIO_Port, &GPIO_InitStruct);

I assume (because none of these definitions are in the code posted) CS_I2C_SPI_Pin specifies the PB6 and PB7 pins. The mode should probably be GPIO_MODE_AF_PP instead. Although, really one should be configuring the pin for open-drain (GPIO_MODE_AF_OD), because I2C devices shouldn't really actively drive the lines high.
 
The following users thanked this post: EVblog1

Offline EVblog1Topic starter

  • Regular Contributor
  • *
  • Posts: 145
  • Country: 00
Re: STM32F I2C Communication Fails
« Reply #7 on: July 13, 2026, 08:13:54 am »
It doesn't appear as though you're configuring the I2C GPIO pins for Alternate Function mode.

Code: [Select]
  /*Configure GPIO pin : CS_I2C_SPI_Pin */
  GPIO_InitStruct.Pin = CS_I2C_SPI_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(CS_I2C_SPI_GPIO_Port, &GPIO_InitStruct);

I assume (because none of these definitions are in the code posted) CS_I2C_SPI_Pin specifies the PB6 and PB7 pins. The mode should probably be GPIO_MODE_AF_PP instead. Although, really one should be configuring the pin for open-drain (GPIO_MODE_AF_OD), because I2C devices shouldn't really actively drive the lines high.

You're right, I had connected the wrong pins.

I had assumed that I2C1 was using PB6 (SCL) and PB7 (SDA), but after checking the generated code, I realized that STM32CubeMX had actually configured:

PB6  ------> I2C1_SCL
PB9  ------> I2C1_SDA

So I corrected the hardware connection and moved SDA from PB7 to PB9.

Unfortunately, the behavior is still exactly the same. The green LED never turns on, indicating that HAL_I2C_IsDeviceReady() is not receiving an ACK from the DS1307. I also checked the I2C bus with my logic analyzer, and I still don't see any I2C activity

So although the pin connection is now correct, the I2C peripheral still doesn't appear to be generating any bus activity.

Code: [Select]
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hi2c->Instance==I2C1)
  {
    /* USER CODE BEGIN I2C1_MspInit 0 */

    /* USER CODE END I2C1_MspInit 0 */

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**I2C1 GPIO Configuration
    PB6     ------> I2C1_SCL
    PB9     ------> I2C1_SDA
    */
    GPIO_InitStruct.Pin = Audio_SCL_Pin|Audio_SDA_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* Peripheral clock enable */
    __HAL_RCC_I2C1_CLK_ENABLE();
    /* USER CODE BEGIN I2C1_MspInit 1 */

    /* USER CODE END I2C1_MspInit 1 */

  }

}
 

Offline EVblog1Topic starter

  • Regular Contributor
  • *
  • Posts: 145
  • Country: 00
Re: STM32F I2C Communication Fails
« Reply #8 on: July 13, 2026, 08:19:28 am »

Just step through the code in debug mode to check whether each register is set correctly.
That’s a method used with older microcontrollers. I do it occasionally myself, but gdb will tell you everything you need to know.

.

I tried running the program in debug mode, but I don't know why execution stops at line 62.

 

Online squadchannel

  • Super Contributor
  • ***
  • Posts: 1273
  • Country: jp
  • deepl translate user
Re: STM32F I2C Communication Fails
« Reply #9 on: July 13, 2026, 09:50:12 am »
No, it hasn't stopped.

First, set a breakpoint. You can set a breakpoint by double-clicking to the left of the line number where you want the code to stop. A circle should appear.
Then, when you run the debug, the code will stop at that line.
When it stops, an arrow will appear at that line.


It doesn't just look like it's stopped; it's actually already running freely.

CubeIDE has a long-standing bug: when you start debugging, the startup file opens, but it's okay to close it.

To access the I/O registers, go to the "SFR" tab. You can check the reference manual to see what’s missing.
« Last Edit: July 13, 2026, 10:01:09 am by squadchannel »
 
The following users thanked this post: EVblog1

Offline EVblog1Topic starter

  • Regular Contributor
  • *
  • Posts: 145
  • Country: 00
Re: STM32F I2C Communication Fails
« Reply #10 on: July 13, 2026, 10:05:31 am »
No, it hasn't stopped.

First, set a breakpoint. You can set a breakpoint by double-clicking to the left of the line number where you want the code to stop. A circle should appear.
Then, when you run the debug, the code will stop at that line.
When it stops, an arrow will appear at that line.
(Attachment Link)

It doesn't just look like it's stopped; it's actually already running freely.

CubeIDE has a long-standing bug: when you start debugging, the startup file opens, but it's okay to close it.


I think that's exactly what I did. I set a breakpoint, started the debugger, and the arrow initially stopped at the HAL_Init(); line. Then I clicked the Run button, expecting the program to continue and stop at my breakpoint inside main(), but it never entered the if statement where I had placed the breakpoint.

I can attach a screenshot

 

Online squadchannel

  • Super Contributor
  • ***
  • Posts: 1273
  • Country: jp
  • deepl translate user
Re: STM32F I2C Communication Fails
« Reply #11 on: July 13, 2026, 10:31:17 am »
If that's the case, it means the breakpoint hasn't been reached.
The fact that the red LED is lit probably means it's not HAL_OK.

Since the return value of HAL_I2C_IsDeviceReady is stored in "status", right-click on status, select "Add Watch Expression...", and you'll be able to check the value on the “Expressions” tab.

You’ll have to figure out for yourself what error that value indicates.
Right-click HAL_I2C_IsDeviceReady and select "Open Declaration" to view the declaration.
 

Offline EVblog1Topic starter

  • Regular Contributor
  • *
  • Posts: 145
  • Country: 00
Re: STM32F I2C Communication Fails
« Reply #12 on: July 13, 2026, 11:28:17 am »
Since the return value of HAL_I2C_IsDeviceReady is stored in "status", right-click on status, select "Add Watch Expression...", and you'll be able to check the value on the “Expressions” tab.

You’ll have to figure out for yourself what error that value indicates.
Right-click HAL_I2C_IsDeviceReady and select "Open Declaration" to view the declaration.

I added a __NOP(); after HAL_I2C_IsDeviceReady() and placed a breakpoint on the __NOP() instruction so I could inspect the return value after the function completed. The debugger shows status = HAL_ERROR



Does anyone know how to make an attached image smaller in a forum post?
« Last Edit: July 13, 2026, 11:35:19 am by EVblog1 »
 

Online squadchannel

  • Super Contributor
  • ***
  • Posts: 1273
  • Country: jp
  • deepl translate user
Re: STM32F I2C Communication Fails
« Reply #13 on: July 13, 2026, 11:33:35 am »
You can use nop but you can also just set a breakpoint at isdeviceready and click "Step Over".
 

Offline EVblog1Topic starter

  • Regular Contributor
  • *
  • Posts: 145
  • Country: 00
Re: STM32F I2C Communication Fails
« Reply #14 on: July 13, 2026, 11:53:28 am »
You can use nop but you can also just set a breakpoint at isdeviceready and click "Step Over".
Yes, that worked. so now I'm trying to figure out why HAL_I2C_IsDeviceReady() is returning HAL_ERROR
 

Offline 8goran8

  • Contributor
  • Posts: 40
  • Country: cs
Re: STM32F I2C Communication Fails
« Reply #15 on: July 13, 2026, 01:06:51 pm »
Pins PB6 and PB9 on the STM32F407G-DISC1 board already have 4K7 pull-up resistors.
 

Online squadchannel

  • Super Contributor
  • ***
  • Posts: 1273
  • Country: jp
  • deepl translate user
Re: STM32F I2C Communication Fails
« Reply #16 on: July 13, 2026, 01:26:52 pm »
GPIO and RCC settings
This is how it's supposed to be...

RCC_AHB1ENR
    GPIOBEN = 0b1

RCC_APB1ENR
    I2C1EN = 0b1

GPIOB_MODER
    MODER6 = 0b10   (alretnate IO mode)
    MODER7 = 0b10   (alretnate IO mode)

GPIOB_OTR
    MODER6 = 0b10    (open-drain mode)
    MODER7 = 0b10    (open-drain mode)

GPIOB_AFRL
    AFRL6 = 0b0100    (alternate function 4 = I2C1)
    AFRL7 = 0b0100    (alternate function 4 = I2C1)

If it's configured that way, the I2C register must be wrong.
 

Offline EVblog1Topic starter

  • Regular Contributor
  • *
  • Posts: 145
  • Country: 00
Re: STM32F I2C Communication Fails
« Reply #17 on: July 13, 2026, 02:39:55 pm »
I removed the unnecessary code from the project and reduced it to a simple I2C test. The STM32 is now generating the I2C sequence correctly but the DS1307 is not acknowledging its address. I'm uploading my logic analyzer capture and the test code.

One thing I also noticed is that STM32CubeMX/STM32CubeIDE sometimes doesn't generate the complete initialization code after configuration changes



Code: [Select]
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_host.h"
HAL_StatusTypeDef status;


/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

I2S_HandleTypeDef hi2s3;

SPI_HandleTypeDef hspi1;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);



int main(void)
{


  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();


  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();



  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  status = HAL_I2C_IsDeviceReady(&hi2c1, (0x68 << 1), 3, 100);

      if(status == HAL_OK)
      {
          HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);   // Green LED
          HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
      }
      else
      {
          HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
          HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);   // Red LED
      }

      HAL_Delay(500);

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

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  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_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

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

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  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();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}



/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  /* USER CODE BEGIN MX_GPIO_Init_1 */

  /* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOE_CLK_ENABLE();
  __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();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(CS_I2C_SPI_GPIO_Port, CS_I2C_SPI_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(OTG_FS_PowerSwitchOn_GPIO_Port, OTG_FS_PowerSwitchOn_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOD, LD4_Pin|LD3_Pin|LD5_Pin|LD6_Pin
                          |Audio_RST_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : CS_I2C_SPI_Pin */
  GPIO_InitStruct.Pin = CS_I2C_SPI_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(CS_I2C_SPI_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : OTG_FS_PowerSwitchOn_Pin */
  GPIO_InitStruct.Pin = OTG_FS_PowerSwitchOn_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(OTG_FS_PowerSwitchOn_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : PDM_OUT_Pin */
  GPIO_InitStruct.Pin = PDM_OUT_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
  HAL_GPIO_Init(PDM_OUT_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : B1_Pin */
  GPIO_InitStruct.Pin = B1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : BOOT1_Pin */
  GPIO_InitStruct.Pin = BOOT1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(BOOT1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : CLK_IN_Pin */
  GPIO_InitStruct.Pin = CLK_IN_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
  HAL_GPIO_Init(CLK_IN_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : LD4_Pin LD3_Pin LD5_Pin LD6_Pin
                           Audio_RST_Pin */
  GPIO_InitStruct.Pin = LD4_Pin|LD3_Pin|LD5_Pin|LD6_Pin
                          |Audio_RST_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  /*Configure GPIO pin : OTG_FS_OverCurrent_Pin */
  GPIO_InitStruct.Pin = OTG_FS_OverCurrent_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(OTG_FS_OverCurrent_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : MEMS_INT2_Pin */
  GPIO_InitStruct.Pin = MEMS_INT2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(MEMS_INT2_GPIO_Port, &GPIO_InitStruct);

  /* USER CODE BEGIN MX_GPIO_Init_2 */

  /* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* 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();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
 

Online squadchannel

  • Super Contributor
  • ***
  • Posts: 1273
  • Country: jp
  • deepl translate user
Re: STM32F I2C Communication Fails
« Reply #18 on: July 13, 2026, 03:08:20 pm »
page 6 on ds1307 datasheets,
Quote
VBAT
..... If a backup supply is not required, VBAT must be grounded. ......
 

Offline EVblog1Topic starter

  • Regular Contributor
  • *
  • Posts: 145
  • Country: 00
Re: STM32F I2C Communication Fails
« Reply #19 on: July 13, 2026, 03:42:22 pm »
page 6 on ds1307 datasheets,
Quote
VBAT
..... If a backup supply is not required, VBAT must be grounded. ......
I connected VBAT to GND since I'm not using a backup battery. Unfortunately, the DS1307 still doesn't acknowledge its I2C address.
At the moment I'm using 4.7 kΩ pull-up resistors from SDA and SCL to 3.3 V,  Should I instead connect the SDA and SCL pull-up resistors to 5 V
 

Offline HwAoRrDk

  • Super Contributor
  • ***
  • Posts: 1931
  • Country: gb
Re: STM32F I2C Communication Fails
« Reply #20 on: July 13, 2026, 06:41:05 pm »
At the moment I'm using 4.7 kΩ pull-up resistors from SDA and SCL to 3.3 V,  Should I instead connect the SDA and SCL pull-up resistors to 5 V

No. A 3.3V high logic level should still be plenty good enough for the DS1307; the datasheet specifies a minimum of 2.2V for a logic '1'.

But it's not always a given that a 5V device will have logic level thresholds that are compatible with 3.3V, so generally logic-level translation is used when interfacing I2C between different supply voltages.
 

Offline cv007

  • Super Contributor
  • ***
  • Posts: 1061
Re: STM32F I2C Communication Fails
« Reply #21 on: July 13, 2026, 07:44:13 pm »
Quote
Although, really one should be configuring the pin for open-drain (GPIO_MODE_AF_OD), because I2C devices shouldn't really actively drive the lines high.
For the G0 series the use of push-pull works, so the i2c peripheral must be controlling more than just the output value for a pin (otherwise the sda pin would not be functional in the push-pull mode). Although the datasheet i/o pin diagram does not show it the i2c peripheral probably has access to the pins mode bit 0- 0b01=output, 0b10=AF, 0b00=input, so the mode bit 0 becomes the bit that gets controlled by i2c and the pin output value remains at 0, high=input=0b10, low=output=0b11. The state of the mode bitfield would always returns to 0b10 which is AF mode so also probably not detectable whether this is what is happening. This may have been done to make sure the i2c pins are never driving the pin high regardless of what the user has done with the pins OTYPE bitfield. Maybe the other stm32 series are the same.
 

Offline EVblog1Topic starter

  • Regular Contributor
  • *
  • Posts: 145
  • Country: 00
Re: STM32F I2C Communication Fails
« Reply #22 on: July 14, 2026, 12:19:44 pm »
To rule out a problem with the DS1307, I tried interfacing a different I2C device, an AT24C02 EEPROM. The only change I made in the code was the slave address:

Code: [Select]
// AT24C02 EEPROM
HAL_I2C_IsDeviceReady(&hi2c1, (0x50 << 1), 3, 100);

I captured the I2C bus using a logic analyzer. The AT24C02 also did not acknowledge its address, and I still did not get the expected I²C communication. This suggests the issue is not specific to the DS1307.

 

Online squadchannel

  • Super Contributor
  • ***
  • Posts: 1273
  • Country: jp
  • deepl translate user
Re: STM32F I2C Communication Fails
« Reply #23 on: July 14, 2026, 12:24:56 pm »
check the SCL/SDA signals on an oscilloscope.
 

Offline EVblog1Topic starter

  • Regular Contributor
  • *
  • Posts: 145
  • Country: 00
Re: STM32F I2C Communication Fails
« Reply #24 on: July 14, 2026, 01:18:45 pm »
check the SCL/SDA signals on an oscilloscope.
I don't have an oscilloscope. I only have a logic analyzer
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

-->