cancel
Showing results for 
Search instead for 
Did you mean: 

Demo FYI: ESP32 AND STM32 I2C INTERFACE

tantheman
Associate

 

STM32 (I²C Master) → ESP32 (I²C Slave) “WASD” Command Link with UART Input

Summary

This project establishes a reliable data path from a PC to an STM32 microcontroller over UART, and from the STM32 to an ESP32 over I²C. The user types a line containing WASD characters in a serial terminal connected to the STM32. Upon pressing Enter, the STM32 transmits only the valid WASD bytes over I²C to the ESP32. The ESP32 runs in true I²C slave mode and logs each received command. The design emphasizes correct I²C electrical configuration (external pull-ups), address handling in STM32 HAL, and predictable serial console behavior.


Hardware Setup

  • MCU (Master): STM32F103 (I²C1: PB6=SCL, PB7=SDA; UART1: PA9=TX, PA10=RX).

  • Target (Slave): ESP32 family device.

    • Classic ESP32: SDA=GPIO21, SCL=GPIO22.

    • ESP32-S3: SDA=GPIO8, SCL=GPIO9.

  • Pull-ups (mandatory): 4.7 kΩ from SDA→3.3 V and SCL→3.3 V (one pair for the entire bus).

  • Common reference: Tie grounds together (STM32, ESP32, and any USB-TTL adapters).

  • I²C speed: Start at 100 kHz. Keep wiring short for signal integrity.

GPIO modes on STM32:

  • I²C pins as Alternate Function Open-Drain, No Pull.

  • UART pins at standard settings for 115200 8N1.


Firmware Overview

STM32 (Master, HAL)

  • Collects a line of input from the UART. The line terminates on CRor LF.

  • Filters out only WASD(case-insensitive) from the collected line.

  • Transmits each valid character as a 1-byte I²C write to the slave at address 0x28.

Key API usage (address parameter):

 

 
 

 

 

This shifts the 7-bit address to the “8-bit address” field as expected by the HAL API variant in use. The peripheral appends the R/W bit automatically.

ESP32 (Slave, Arduino core using ESP-IDF driver)

  • Configured as an I²C slave at 0x28 using the ESP-IDF driver from within Arduino.

  • Internal pull-ups are disabled in software; external 4.7 kΩ pull-ups are required.

  • Continuously reads with and prints OK WASD for valid bytes.

 

 

 

Key Fixes (Revised)

  1. STM32 HAL address parameter

    • Issue: Passing 0X28 directly to yielded I2C TX Error with this HAL variant.

    • Resolution: Pass the address shifted left by 1, i.e. (0x28<<1). The device’s true address remains 0x28 (7-bit). The HAL parameter represents the 7-bit address in the upper bits of the 8-bit address field; the hardware then appends the R/W bit.

  2. Serial line ending on STM32

    • Issue: Serial monitor “Line ending: None” prevented the newline from being delivered; the UART line reader never completed.

    • Resolution: Set line ending to CR or LF. Pressing Enter now terminates the line and triggers I²C transmission.

  3. Pull-up strategy and bus integrity

    • Issue: Unreliable or floating SCL/SDA, especially with longer pigtails or varied boards.

    • Resolution: Disable internal pulls on the data/clock lines in code and install external 4.7 kΩ pull-up resistors to 3.3 V on both SCL and SDA. This ensures a clean idle high and proper rise time on an open-drain bus.

  4. Pin mapping consistency (ESP32 families)

    • Issue: Using classic-ESP32 pin assumptions (21/22) on ESP32-S3 boards (8/9) or vice-versa causes silent failures.

    • Resolution: For classic ESP32, use SDA=21, SCL=22. For ESP32-S3, use SDA=8, SCL=9. Match the pins you physically wired.

(Note: original list item numbering was compacted; the previously listed “4” was intentionally removed per request.)


Expected Results

  • User input: wasd then enter on the STM32 terminal (CR or LF line ending).

  • STM32 terminal: echoes input, then sent on i2c.

  • ESP32 terminal: WASD 

     
     

Characters outside WASD are ignored by the ESP32 logging logic (they are not transmitted by the STM32).


Troubleshooting Checklist (Fast Path)

  1. ESP32 running in slave mode and prints “Ready @0x28 …”.

  2. Common ground across STM32, ESP32, and any USB-TTL.

  3. Pull-ups present: 4.7 kΩ from SDA→3.3 V and SCL→3.3 V; idle lines ~3.3 V.

  4. Pin mapping correct: PB6↔SCL, PB7↔SDA on STM32; ESP32 pins as per your variant.

  5. HAL call uses shifted address: (0x28<<1).

  6. Serial line ending: CR or LF on the STM32 terminal.

  7. Bus speed: 100 kHz to start; short leads; avoid excessive capacitance.

 
 

You should detect 0x28.


Rationale: Addressing and Signal Integrity

  • Addressing: I²C devices are identified by a 7-bit address. On the wire, the master sends an 8-bit value comprising the 7-bit address plus the R/W bit. Some STM32 HAL variants specify the API parameter as the 8-bit address field (i.e., 7-bit address shifted left by 1). Supplying (addr<<1)to the HAL while leaving the device configured at its 7-bit address ensures consistent behavior.

  • Signal integrity: I²C lines are open-drain. Devices pull the lines low; external resistors pull them high. External 4.7 kΩ pull-ups to 3.3 V establish a defined idle high level and acceptable rise time, improving reliability with mixed boards, jumpers, and typical bench wiring lengths.

 


 

1 ACCEPTED SOLUTION

Accepted Solutions
Andrew Neil
Super User

Is there a question, or are you just presenting this as something others might find useful?

Something seems to have gone wrong with your "Key API usage (address parameter)":

 


@tantheman wrote:

 

AndrewNeil_2-1762794116078.png

 

 

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.

View solution in original post

6 REPLIES 6
Andrew Neil
Super User

Is there a question, or are you just presenting this as something others might find useful?

Something seems to have gone wrong with your "Key API usage (address parameter)":

 


@tantheman wrote:

 

AndrewNeil_2-1762794116078.png

 

 

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

Just something that might be useful.

tantheman
Associate

yes the key api usage was showing highlighted errors while posting ... so just put the code instead ......

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

thank you for this advice.

You might want to fix those missing bits / formatting oddities, then.

 

I edited the title to clarify.

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.

HAL_I2C_Master_Transmit(&hi2c1, (0x28 << 1), &c, 1, 10); key API usage 

 

Bermingham
Associate

Thanks for sharing this detailed setup, @tantheman! The breakdown of HAL address handling, pull-up strategy, and pin mapping is really useful for anyone integrating STM32 with ESP32 over I²C. Clear step-by-step guides like this save a lot of trial-and-error time for mixed MCU setups.