aw9523-embedded
A platform-agnostic embedded-hal driver for the AW9523 16-channel GPIO expander and LED driver.
Features
- 🔌 16 GPIO Pins - Configurable as digital input/output
- 💡 LED Driver Mode - 256-step constant current control for LED dimming
- 🔧
no_stdCompatible - Perfect for embedded systems - 🎯 Platform Agnostic - Uses
embedded-haltraits for maximum portability - ⚡ Flexible Control - Individual pin control or bulk 16-bit operations
- 📡 Interrupt Support - Configurable interrupt detection per pin
- 🔄 Dual Output Modes - Port 0 supports open-drain or push-pull
Hardware Overview
The AW9523 is an I2C-controlled GPIO expander with:
- 16 configurable I/O pins organized as two 8-bit ports
- Each pin supports digital I/O or constant-current LED driving
- I2C interface (default address: 0x58)
- Interrupt capability for input change detection
- Port 0 (pins 0-7): Configurable as open-drain or push-pull
- Port 1 (pins 8-15): Push-pull outputs only
Installation
Add this to your Cargo.toml:
[]
= "0.1"
= "1.0"
Usage Examples
Basic GPIO Control
use ;
// Create device with I2C bus and default address
let mut gpio = new;
// Initialize with default configuration
gpio.init.unwrap;
// Configure pin 0 as output and set it high
gpio.pin_mode.unwrap;
gpio.digital_write.unwrap;
// Configure pin 8 as input and read its state
gpio.pin_mode.unwrap;
let state = gpio.digital_read.unwrap;
LED Dimming
use ;
// Create and initialize device
let mut gpio = new;
gpio.init.unwrap;
// Configure pin 0 for LED mode
gpio.pin_mode.unwrap;
// Set LED brightness (0 = off, 255 = maximum)
gpio.analog_write.unwrap; // 50% brightness
gpio.analog_write.unwrap; // 100% brightness
Bulk Operations
use ;
let mut gpio = new;
gpio.init.unwrap;
// Set multiple pins high at once using bitmasks
gpio.output_gpio.unwrap;
// Read all 16 pins at once
let inputs = gpio.input_gpio.unwrap;
if inputs & AW9523_PIN_5 != 0
// Configure multiple pins as outputs
gpio.configure_direction.unwrap;
// Enable interrupts on multiple pins
gpio.interrupt_enable_gpio.unwrap;
Interrupt Detection
use ;
let mut gpio = new;
gpio.init.unwrap;
// Configure pin as input
gpio.pin_mode.unwrap;
// Enable interrupt for pin 10
gpio.enable_interrupt.unwrap;
// Your code would monitor the hardware interrupt line
// and read the input state when triggered
Async Support
The library provides full async support when the async feature is enabled. This allows non-blocking I2C operations using embedded-hal-async traits.
Enabling Async
Add the async feature to your Cargo.toml:
[]
= { = "0.1", = ["async"] }
= "1.0"
Async Usage Examples
Basic Async GPIO Control
use ;
async
Async LED Control
use ;
async
Async Bulk Operations
use ;
async
Async with Embassy Framework
The async implementation works seamlessly with Embassy and other async runtimes:
use Spawner;
use ;
async
async
Blocking vs Async API Comparison
| Feature | Blocking API | Async API |
|---|---|---|
| Module | Root module | aw9523_embedded::r#async |
| Struct | Aw9523 |
Aw9523Async |
| Trait | embedded_hal::i2c::I2c |
embedded_hal_async::i2c::I2c |
| Method calls | gpio.init().unwrap() |
gpio.init().await.unwrap() |
| Runtime | Blocking execution | Async/await compatible |
All methods available in the blocking API have async equivalents with identical names and signatures (except for the async keyword and .await).
API Overview
Pin Configuration
init()- Initialize device with default configurationreset()- Software resetpin_mode(pin, mode)- Configure single pin (INPUT, OUTPUT, or AW9523_LED_MODE)
Digital I/O
digital_write(pin, state)- Set output pin high/lowdigital_read(pin)- Read input pin stateoutput_gpio(pins)- Set all 16 pins at once (bit mask)input_gpio()- Read all 16 pins at once
LED Control
analog_write(pin, brightness)- Set LED brightness (0-255)configure_led_mode(pins)- Enable LED mode on multiple pins
Interrupts
enable_interrupt(pin, enabled)- Enable/disable interrupt for a pininterrupt_enable_gpio(pins)- Configure interrupts for multiple pins
Bulk Configuration
configure_direction(pins)- Set pin directions for all 16 pins
Additional Methods (Async)
get_chip_id()- Read chip ID register (should return 0x23)open_drain_port0(enabled)- Configure Port 0 as open-drain or push-pull
Pin Constants
The crate provides constants for easy pin referencing:
use ;
// Individual pins: AW9523_PIN_0 through AW9523_PIN_15
// Port notation: AW9523_P0_0 through AW9523_P1_7
// Port groups: AW9523_PORT0_ALL, AW9523_PORT1_ALL
// All pins: AW9523_ALL_PINS
All constants are re-exported in the async module for convenience.
Testing
The library includes comprehensive test coverage for both blocking and async implementations:
# Run blocking tests
# Run async tests
# Run all tests with all features