TCA9534 Driver
A platform-independent Rust driver for the TCA9534 I2C IO expander, with optional embedded-hal integration.
🚀 Key Features
- 🔧 Zero Dependencies: Core driver works without any external dependencies
- 🎯 Optional embedded-hal Integration: Seamless integration when needed
- 🔄 Sync & Async Support: Both synchronous and asynchronous operations
- 📦
no_stdCompatible: Perfect for embedded systems - 🎨 Ergonomic API: Simple and intuitive interface
- 📖 Well Documented: Comprehensive documentation and examples
🏗️ Architecture Design
Layered Architecture
┌─────────────────────────────────────┐
│ User Code Layer │
├─────────────────────────────────────┤
│ Convenience Constructors │ <- embedded-hal optional
│ (new_with_default_address) │
├─────────────────────────────────────┤
│ TCA9534 Driver Core │ <- Always available
├─────────────────────────────────────┤
│ Transport Traits │ <- Always available
│ (SyncTransport/AsyncTransport) │
├─────────────────────────────────────┤
│ Transport Implementation Layer │ <- embedded-hal optional
└─────────────────────────────────────┘
📋 Feature-Based Compilation Strategy
Core Principle: Driver core and transport traits are always available, embedded-hal integration is optional
- Default Mode (
full-async): Complete async functionality with embedded-hal integration - Minimal Mode (
default-features = false): Zero dependencies, custom transport only - Sync Mode (
embedded-hal): Synchronous operations with embedded-hal I2C traits - Async Mode (
async+embedded-hal-async): Async/await support with embedded-hal integration
About TCA9534
The TCA9534 is an 8-bit I2C IO expander that provides:
- 8 GPIO pins that can be individually configured as inputs or outputs
- Polarity inversion for input pins
- I2C interface with configurable address (0x20-0x27)
- Low power consumption
- 3.3V and 5V operation
Usage
Dependencies
[]
# Default - includes full async support (async + embedded-hal + embedded-hal-async)
= "0.1"
# Minimal - no external dependencies, sync only
= { = "0.1", = false }
# Sync with embedded-hal support only
= { = "0.1", = false, = ["embedded-hal"] }
# Async only (no embedded-hal)
= { = "0.1", = false, = ["async"] }
# Custom combinations
= { = "0.1", = false, = ["async", "embedded-hal"] }
# With defmt logging support
= { = "0.1", = ["defmt"] }
Available Features
async- Enables async/await support for TCA9534Asyncembedded-hal- Enables embedded-hal v1.0 I2C trait integrationembedded-hal-async- Enables embedded-hal-async I2C trait integrationfull-async- Combinesasync+embedded-hal+embedded-hal-async(included in default)defmt- Enables defmt logging support
Default features: ["full-async"] - provides complete async functionality out of the box.
Basic Example (Synchronous)
Note: For sync-only usage, disable default features in your Cargo.toml:
= { = "0.1", = false, = ["embedded-hal"] }
use ;
// Initialize I2C bus (platform specific)
let i2c = setup_i2c; // Your I2C initialization code
// Create TCA9534 driver with address 0x20
let mut tca9534 = new;
// Or use default address constructor
let mut tca9534 = new_with_default_address;
//Or use transport which implements SyncTransport
let transport = new;
let mut tca9534 = new;
// Initialize the device
tca9534.init?;
// Configure pin 0 as output, others as input
tca9534.set_pin_config?;
for pin in 1..8
// Set pin 0 to high
tca9534.set_pin_output?;
// Read pin 1 input
let pin1_level = tca9534.read_pin_input?;
// Toggle pin 0
tca9534.toggle_pin_output?;
Custom Transport Example (No Dependencies)
Note: For zero dependencies, use minimal mode:
= { = "0.1", = false }
use ;
// Implement your own transport
// Use with custom transport
let transport = new;
let mut tca9534 = new;
Async Example
Note: Async support is enabled by default with full-async feature.
use ;
// Initialize async I2C bus (platform specific)
let i2c = setup_async_i2c; // Your async I2C initialization code
// Create TCA9534 driver
let mut tca9534 = new;
// Initialize the device
tca9534.init.await?;
// Configure and use pins
tca9534.set_pin_config.await?;
tca9534.set_pin_output.await?;
let input_level = tca9534.read_pin_input.await?;
Port-wide Operations
// Configure all pins at once (1=input, 0=output)
tca9534.set_port_config?; // Pins 0-3 output, 4-7 input
// Set all output pins at once
tca9534.write_output_port?; // Set pins 0-3 high
// Read all input pins at once
let input_state = tca9534.read_input_port?;
API Overview
Core Functions
new(transport, address)- Create new driver instanceinit()- Initialize device with default settingsset_pin_config(pin, config)- Configure pin as input or outputset_pin_output(pin, level)- Set output pin high or lowread_pin_input(pin)- Read input pin leveltoggle_pin_output(pin)- Toggle output pin state
Port-wide Operations
set_port_config(config)- Configure all pins at oncewrite_output_port(value)- Set all output pins at onceread_input_port()- Read all input pins at onceread_output_port()- Read current output register value
Advanced Features
set_pin_polarity(pin, polarity)- Set input polarity (normal/inverted)set_port_polarity(polarity)- Set polarity for all pinsaddress()/set_address(addr)- Get/set I2C address
Register Map
| Register | Address | Description |
|---|---|---|
| Input Port | 0x00 | Read input pin levels |
| Output Port | 0x01 | Set output pin levels |
| Polarity Inversion | 0x02 | Configure input polarity |
| Configuration | 0x03 | Configure pin directions |
I2C Addresses
The TCA9534 supports 8 different I2C addresses based on the A2, A1, A0 pins:
| A2 | A1 | A0 | Address | Constant |
|---|---|---|---|---|
| 0 | 0 | 0 | 0x20 | addresses::ADDR_000 |
| 0 | 0 | 1 | 0x21 | addresses::ADDR_001 |
| 0 | 1 | 0 | 0x22 | addresses::ADDR_010 |
| 0 | 1 | 1 | 0x23 | addresses::ADDR_011 |
| 1 | 0 | 0 | 0x24 | addresses::ADDR_100 |
| 1 | 0 | 1 | 0x25 | addresses::ADDR_101 |
| 1 | 1 | 0 | 0x26 | addresses::ADDR_110 |
| 1 | 1 | 1 | 0x27 | addresses::ADDR_111 |
Error Handling
The driver provides minimal error handling focused on essential validation:
InvalidPin- Pin number out of range (must be 0-7)I2cError(E)- Underlying I2C transport error
Additional error types can be added as needed for your specific use case.
Platform Support
With embedded-hal Integration
This driver works with any platform that implements the embedded-hal I2C traits:
- STM32 (via
stm32halfamily crates) - ESP32 (via
esp-hal) - Raspberry Pi Pico (via
rp2040-hal) - Arduino-style boards (via
arduino-hal) - Linux (via
linux-embedded-hal) - And many more!
Without Dependencies
You can use this driver on any platform by implementing the SyncTransport or AsyncTransport traits for your I2C implementation.
Features
embedded-hal- Enable embedded-hal I2C trait integrationembedded-hal-async- Enable embedded-hal async I2C trait integrationasync- Enable async/await support (requires async transport)defmt- Enable defmt logging support
Examples
See the examples/ directory for complete examples:
basic_usage- Complete example using STM32G431 with embassy-rs
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.