Skip to content

MCP23017

Microchip MCP23017 16-bit I²C GPIO expander (two 8-bit ports, IODIR / GPIO / OLAT register map).

Live catalog

Prefer labwired_describe with the catalog id over guessing pins or addresses.

Status at a glance

Aspect Status
Catalog id mcp23017
Bus I²C
Address 0x20 (A2/A1/A0 select 0x20–0x27)
Source configs/devices/mcp23017.yaml (declarative, no Rust model)
Datasheet Microchip MCP23017/MCP23S17 DS20001952D, §3.2 I²C interface, Table 3-1 / 3-5, §3.5 registers
Tier smoke-proven (register-level tests: crates/core/tests/everyday_sensor_set.rs)

Pins / attachment

Pin / net Role
SDA / SCL I²C
GPA0..GPA7, GPB0..GPB7 Output pads, bound through the optional gpa0_pin..gpb7_pin keys
INTA / INTB Not modelled
VDD/GND Power (digital twin)

Support matrix

Behavior Status Notes
BANK = 0 register map 0x00–0x15, power-on values ✅ IODIR 0xFF, everything else 0x00
Sequential mode (pointer increments, 0x15 → 0x00) ✅ 2-byte GPIOA/GPIOB bursts land on both
GPIO write → OLAT, OLAT → output pads gated by IODIR ✅ A pin turned to output drives its latch at once
GPIO read: latch on outputs, posed level on inputs, IPOL inversion ✅ Input levels come from port_a / port_b
IOCON at 0x0A and 0x0B (one register), bit 0 reads 0 ✅
External pad levels reaching GPIO ❌ Same gap as PCF8574 — use the port_a / port_b stimulus
GPPU pull-ups ⚠️ Stored only
Interrupt-on-change, INTF/INTCAP, INTA/INTB ❌ INTF/INTCAP read 0x00
IOCON.BANK = 1 re-mapping, SEQOP byte mode ❌ Stored only
Releasing a pad when a pin goes back to input ❌ The pad holds its last driven level

Stimulus

Host inputs: port_a, port_b (0–255) — the levels posed on input pins.

How to run

  1. Place the part and an MCU in Playground, or add it to a system YAML:
    external_devices:
      - id: "expander"
        type: "mcp23017"
        connection: "i2c0"   # the bus id your chip system uses
        config:
          gpa0_pin: "PC0"
          gpb7_pin: "PC1"
    
  2. Agent: labwired_list → labwired_describe id=mcp23017 → wire → labwired_validate → labwired_run / labwired_verify.
  3. Register-level smoke: cargo test -p labwired-core --test everyday_sensor_set — the 22-byte power-on map, the 0x15 → 0x00 rollover, IOCON mirroring and GPIO → OLAT. The same file's negative control proves the check fails against a part that answers only 0x00 or only 0xFF; mcp23017_tracks_stimulus checks IODIR-gated pad drives and IPOL.

Limitations

  • GPA7 and GPB7 are output-only on the MCP23017 (rev. D); the twin stores IODIR bit 7 as written and does not enforce this.

See the YAML header for the full datasheet trace and every named approximation.