#embedded-hal #spi #spi-bus #driver #pin #io #expander

no-std mcp23s17

MCP23S17 driver A driver for the MCP23S17 16 bit I/O expander chip addressed over the SPI bus

2 unstable releases

new 0.2.0 Dec 12, 2024
0.1.0 Nov 6, 2023

#446 in Hardware support

Download history 5/week @ 2024-09-23 152/week @ 2024-12-09

152 downloads per month

MIT license

31KB
361 lines

MCP23S17 driver

Crates.io Crates.io Crates.io

A driver for the MCP23S17 I/O expander which is accessed over an SPI bus.

Example usage

// spi_device implements the SpiDevice trait from embedded_hal >= 1.0.0
// The hardware address corresponds to the way the pins A0, A1, A2 are physically connected
let mut mcp23s17 = mcp23s17::Mcp23s17::new(spi_device, 0b000).ok().unwrap();

// Configure pin GPA0 as an output
mcp23s17.pin_mode(0, mcp23s17::PinMode::Output).ok().unwrap();
// Set pin GPA0 high
mcp23s17.set_high(0);

// Configure pin GPA1 as an pullup input
mcp23s17.pin_mode(1, mcp23s17::PinMode::InputPullup).ok().unwrap();
// Read GPA1's level
let is_high = mcp23s17.read(1);

Example implementation of the SpiDevice trait

// Assuming the SpiBus trait is implemented for Spi

spi_device = MySpiDevice::new(spi, cs);

struct MySpiDevice {
    spi: Spi,
    cs: SpiCsPin,
}

impl MySpiDevice{
    fn new(spi: Spi, mut cs: SpiCsPin) -> MySpiDevice {
        // IMPORTANT, otherwise MCP23S17 might not work
        cs.set_high();

        MySpiDevice { spi, cs }
    }
}

impl embedded_hal::spi::SpiDevice for MySpiDevice {
    fn transaction(
        &mut self,
        operations: &mut [embedded_hal::spi::Operation<'_, u8>],
    ) -> Result<(), Self::Error> {  
        for operation in operations {
            match operation {
                embedded_hal::spi::Operation::DelayNs(_) => {}
                _ => {
                    self.cs.set_low();
                }
            }
            match operation {
                embedded_hal::spi::Operation::Read(words) => {
                    let _ = embedded_hal::spi::SpiBus::read(&mut self.spi, words);
                }
                embedded_hal::spi::Operation::Write(words) => {
                    let _ = embedded_hal::spi::SpiBus::write(&mut self.spi, words);
                }
                embedded_hal::spi::Operation::Transfer(read, write) => {
                    let _ = embedded_hal::spi::SpiBus::transfer(&mut self.spi, read, write);
                }
                embedded_hal::spi::Operation::TransferInPlace(words) => {
                    let _ = embedded_hal::spi::SpiBus::transfer_in_place(&mut self.spi, words);
                }
                embedded_hal::spi::Operation::DelayNs(ns) => {
                    delay_us(*ns / 1000);
                }
            }
            match operation {
                embedded_hal::spi::Operation::DelayNs(_) => {}
                _ => {
                    self.cs.set_high();
                }
            }                   
        }
        Ok(())
    }
}

impl embedded_hal::spi::ErrorType for MySpiDevice {
    type Error = Infallible;
}

impl core::fmt::Debug for MySpiDevice {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "MySpi")
    }
}

Acknowledgements

Many of the documentation comments in this library are taken direct from the MCP23S17 datasheet and are © 2005-2022 Microchip Technology Inc. and its subsidiaries.

Inspired by this Arduino MCP23S17 Library and the RPPAL MCP23S17 Library

Dependencies

~160KB