Skip to main content

I2c

Struct I2c 

Source
pub struct I2c<'d, Dm: DriverMode> { /* private fields */ }
Expand description

I2C driver

§Examples

use esp_hal::i2c::master::{Config, I2c};
let mut i2c = I2c::new(peripherals.I2C0, Config::default())?
    .with_sda(peripherals.GPIO1)
    .with_scl(peripherals.GPIO2);

let mut data = [0u8; 22];
i2c.write_read(DEVICE_ADDR, &[0xaa], &mut data)?;

Implementations§

Source§

impl<'d> I2c<'d, Blocking>

Source

pub fn new(i2c: impl Instance + 'd, config: Config) -> Result<Self, ConfigError>

Creates a new I2C instance.

§Examples
use esp_hal::i2c::master::{Config, I2c};
let i2c = I2c::new(peripherals.I2C0, Config::default())?
    .with_sda(peripherals.GPIO1)
    .with_scl(peripherals.GPIO2);
§Errors

ConfigError when bus frequency or timeout passed in config is invalid.

Source

pub fn into_async(self) -> I2c<'d, Async>

Reconfigures the driver to operate in Async mode.

See the Async documentation for an example on how to use this method.

Source

pub fn set_interrupt_handler(&mut self, handler: InterruptHandler)

Available on crate feature unstable only.

Registers an interrupt handler for the peripheral on the current core.

Replaces any previously registered interrupt handlers.

The default/unhandled interrupt handler can be restored by passing DEFAULT_INTERRUPT_HANDLER.

§Panics

Panics if passed interrupt handler is invalid (e.g. has priority None)

§Stability

This API is marked as unstable and is only available when the unstable crate feature is enabled. This comes with no stability guarantees, and could be changed or removed at any time.

Source

pub fn listen(&mut self, interrupts: impl Into<EnumSet<Event>>)

Available on crate feature unstable only.

Listens for the given interrupts.

§Stability

This API is marked as unstable and is only available when the unstable crate feature is enabled. This comes with no stability guarantees, and could be changed or removed at any time.

Source

pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<Event>>)

Available on crate feature unstable only.

Unlistens from the given interrupts.

§Stability

This API is marked as unstable and is only available when the unstable crate feature is enabled. This comes with no stability guarantees, and could be changed or removed at any time.

Source

pub fn interrupts(&mut self) -> EnumSet<Event>

Available on crate feature unstable only.

Returns the asserted interrupts.

§Stability

This API is marked as unstable and is only available when the unstable crate feature is enabled. This comes with no stability guarantees, and could be changed or removed at any time.

Source

pub fn clear_interrupts(&mut self, interrupts: EnumSet<Event>)

Available on crate feature unstable only.

Resets asserted interrupts.

§Stability

This API is marked as unstable and is only available when the unstable crate feature is enabled. This comes with no stability guarantees, and could be changed or removed at any time.

Source§

impl<'d> I2c<'d, Async>

Source

pub fn into_blocking(self) -> I2c<'d, Blocking>

Reconfigures the driver to operate in Blocking mode.

See the Blocking documentation for an example on how to use this method.

Source

pub async fn write_async<A: Into<I2cAddress>>( &mut self, address: A, buffer: &[u8], ) -> Result<(), Error>

Writes bytes to slave with given address.

Dropping the returned Future aborts the transfer, but blocks while the driver finishes clearing and releasing the bus.

§Examples
use esp_hal::i2c::master::{Config, I2c};
const DEVICE_ADDR: u8 = 0x77;
let mut i2c = I2c::new(peripherals.I2C0, Config::default())?
    .with_sda(peripherals.GPIO1)
    .with_scl(peripherals.GPIO2)
    .into_async();

i2c.write_async(DEVICE_ADDR, &[0xaa]).await?;
Source

pub async fn read_async<A: Into<I2cAddress>>( &mut self, address: A, buffer: &mut [u8], ) -> Result<(), Error>

Reads enough bytes from slave with address to fill buffer.

Dropping the returned Future aborts the transfer, but blocks while the driver finishes clearing and releasing the bus.

§Examples
use esp_hal::i2c::master::{Config, I2c};
const DEVICE_ADDR: u8 = 0x77;
let mut i2c = I2c::new(peripherals.I2C0, Config::default())?
    .with_sda(peripherals.GPIO1)
    .with_scl(peripherals.GPIO2)
    .into_async();

let mut data = [0u8; 22];
i2c.read_async(DEVICE_ADDR, &mut data).await?;
§Errors

Error when the passed buffer has zero length.

Source

pub async fn write_read_async<A: Into<I2cAddress>>( &mut self, address: A, write_buffer: &[u8], read_buffer: &mut [u8], ) -> Result<(), Error>

Writes bytes to slave with given address and then reads enough bytes to fill buffer in a single transaction.

Dropping the returned Future aborts the transfer, but blocks while the driver finishes clearing and releasing the bus.

§Examples
use esp_hal::i2c::master::{Config, I2c};
const DEVICE_ADDR: u8 = 0x77;
let mut i2c = I2c::new(peripherals.I2C0, Config::default())?
    .with_sda(peripherals.GPIO1)
    .with_scl(peripherals.GPIO2)
    .into_async();

let mut data = [0u8; 22];
i2c.write_read_async(DEVICE_ADDR, &[0xaa], &mut data)
    .await?;
§Errors

Error when the passed buffer has zero length.

Source

pub async fn transaction_async<'a, A: Into<I2cAddress>>( &mut self, address: A, operations: impl IntoIterator<Item = &'a mut Operation<'a>>, ) -> Result<(), Error>

Executes the provided operations on the I2C bus as a single transaction.

Dropping the returned Future aborts the transfer, but blocks while the driver finishes clearing and releasing the bus.

Transaction contract:

  • Before executing the first operation an ST is sent automatically. This is followed by SAD+R/W as appropriate.

  • Data from adjacent operations of the same type are sent after each other without an SP or SR.

  • Between adjacent operations of a different type an SR and SAD+R/W is sent.

  • After executing the last operation an SP is sent automatically.

  • If the last operation is a Read the master does not send an acknowledge for the last byte.

  • ST = start condition

  • SAD+R/W = slave address followed by bit 1 to indicate reading or 0 to indicate writing

  • SR = repeated start condition

  • SP = stop condition

On ESP32 and ESP32-S2 there might be issues combining large read/write operations with small (<3 bytes) read/write operations.

§Examples
use esp_hal::i2c::master::{Config, I2c, Operation};
const DEVICE_ADDR: u8 = 0x77;
let mut i2c = I2c::new(peripherals.I2C0, Config::default())?
    .with_sda(peripherals.GPIO1)
    .with_scl(peripherals.GPIO2)
    .into_async();

let mut data = [0u8; 22];
i2c.transaction_async(
    DEVICE_ADDR,
    &mut [Operation::Write(&[0xaa]), Operation::Read(&mut data)],
)
.await?;
§Errors

Error when the buffer passed to an Operation has zero length.

Source§

impl<'d, Dm> I2c<'d, Dm>
where Dm: DriverMode,

Source

pub fn with_sda( self, sda: impl PeripheralInput<'d> + PeripheralOutput<'d>, ) -> Self

Connects a pin to the I2C SDA signal.

If called with a pin singleton (e.g. GPIO2), the pin is configured to use the internal pull-up resistor. If that is undesired, call this method with a fully configured Flex pin driver. With Flex, the I2C driver does not change the pin configuration.

This will replace previous pin assignments for this signal.

§Examples

Basic usage

use esp_hal::i2c::master::{Config, I2c};

let i2c = I2c::new(peripherals.I2C0, Config::default())?.with_sda(peripherals.GPIO2);

Using Flex to configure the pin

use esp_hal::{
    gpio::{DriveMode, Flex, OutputConfig},
    i2c::master::{Config, I2c},
};

let mut sda = Flex::new(peripherals.GPIO2);

// The default pullup setting is `Pull::None`.
sda.apply_output_config(&OutputConfig::default().with_drive_mode(DriveMode::OpenDrain));
sda.set_input_enable(true);
sda.set_output_enable(true);
// Initial pin state to avoid the pin to go low during peripheral configuration.
sda.set_high();

let i2c = I2c::new(peripherals.I2C0, Config::default())?.with_sda(sda);
Source

pub fn with_scl( self, scl: impl PeripheralInput<'d> + PeripheralOutput<'d>, ) -> Self

Connects a pin to the I2C SCL signal.

If called with a pin singleton (e.g. GPIO2), the pin is configured to use the internal pull-up resistor. If that is undesired, call this method with a fully configured Flex pin driver. With Flex, the I2C driver does not change the pin configuration.

This will replace previous pin assignments for this signal.

§Examples

Basic usage

use esp_hal::i2c::master::{Config, I2c};

let i2c = I2c::new(peripherals.I2C0, Config::default())?.with_scl(peripherals.GPIO2);

Using Flex to configure the pin

use esp_hal::{
    gpio::{DriveMode, Flex, OutputConfig},
    i2c::master::{Config, I2c},
};

let mut scl = Flex::new(peripherals.GPIO2);

// The default pullup setting is `Pull::None`.
scl.apply_output_config(&OutputConfig::default().with_drive_mode(DriveMode::OpenDrain));
scl.set_input_enable(true);
scl.set_output_enable(true);
// Initial pin state to avoid the pin to go low during peripheral configuration.
scl.set_high();

let i2c = I2c::new(peripherals.I2C0, Config::default())?.with_scl(scl);
Source

pub fn write<A: Into<I2cAddress>>( &mut self, address: A, buffer: &[u8], ) -> Result<(), Error>

Writes bytes to slave with given address.

§Examples
use esp_hal::i2c::master::{Config, I2c};
i2c.write(DEVICE_ADDR, &[0xaa])?;
Source

pub fn read<A: Into<I2cAddress>>( &mut self, address: A, buffer: &mut [u8], ) -> Result<(), Error>

Reads enough bytes from slave with address to fill buffer.

§Examples
use esp_hal::i2c::master::{Config, I2c};
let mut data = [0u8; 22];
i2c.read(DEVICE_ADDR, &mut data)?;
§Errors

Error when the passed buffer has zero length.

Source

pub fn write_read<A: Into<I2cAddress>>( &mut self, address: A, write_buffer: &[u8], read_buffer: &mut [u8], ) -> Result<(), Error>

Writes bytes to slave with given address and then reads enough bytes to fill buffer in a single transaction.

§Examples
use esp_hal::i2c::master::{Config, I2c};
let mut data = [0u8; 22];
i2c.write_read(DEVICE_ADDR, &[0xaa], &mut data)?;
§Errors

Error when the passed buffer has zero length.

Source

pub fn transaction<'a, A: Into<I2cAddress>>( &mut self, address: A, operations: impl IntoIterator<Item = &'a mut Operation<'a>>, ) -> Result<(), Error>

Executes the provided operations on the I2C bus.

Transaction contract:

  • Before executing the first operation an ST is sent automatically. This is followed by SAD+R/W as appropriate.

  • Data from adjacent operations of the same type are sent after each other without an SP or SR.

  • Between adjacent operations of a different type an SR and SAD+R/W is sent.

  • After executing the last operation an SP is sent automatically.

  • If the last operation is a Read the master does not send an acknowledge for the last byte.

  • ST = start condition

  • SAD+R/W = slave address followed by bit 1 to indicate reading or 0 to indicate writing

  • SR = repeated start condition

  • SP = stop condition

§Examples
use esp_hal::i2c::master::{Config, I2c, Operation};
let mut data = [0u8; 22];
i2c.transaction(
    DEVICE_ADDR,
    &mut [Operation::Write(&[0xaa]), Operation::Read(&mut data)],
)?;

On ESP32 and ESP32-S2 it is advisable to not combine large read/write operations with small (<3 bytes) read/write operations.

§Errors

Error when the buffer passed to an Operation has zero length.

Source

pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError>

Applies a new configuration.

§Examples
use esp_hal::i2c::master::{Config, I2c};
let mut i2c = I2c::new(peripherals.I2C0, Config::default())?;

i2c.apply_config(&Config::default().with_frequency(Rate::from_khz(400)))?;
§Errors

ConfigError when bus frequency or timeout passed in config is invalid.

Source

pub fn force_scl_low(&mut self, low: bool)

Available on crate feature unstable only.

Drives SCL low (true) or releases it (false).

Forcing a line low interrupts normal peripheral operation — no transactions should be started while a line is held low.

§Stability

This API is marked as unstable and is only available when the unstable crate feature is enabled. This comes with no stability guarantees, and could be changed or removed at any time.

Source

pub fn force_sda_low(&mut self, low: bool)

Available on crate feature unstable only.

Drives SDA low (true) or releases it (false).

Forcing a line low interrupts normal peripheral operation — no transactions should be started while a line is held low.

§Stability

This API is marked as unstable and is only available when the unstable crate feature is enabled. This comes with no stability guarantees, and could be changed or removed at any time.

Trait Implementations§

Source§

impl<'d, Dm: Debug + DriverMode> Debug for I2c<'d, Dm>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<Dm: DriverMode> ErrorType for I2c<'_, Dm>

Source§

type Error = Error

Error type
Source§

impl I2c for I2c<'_, Async>

Source§

async fn transaction( &mut self, address: u8, operations: &mut [EhalOperation<'_>], ) -> Result<(), Self::Error>

Execute the provided operations on the I2C bus as a single transaction. Read more
Source§

async fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error>

Reads enough bytes from slave with address to fill buffer. Read more
Source§

async fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error>

Writes bytes to slave with address address. Read more
Source§

async fn write_read( &mut self, address: A, write: &[u8], read: &mut [u8], ) -> Result<(), Self::Error>

Writes bytes to slave with address address and then reads enough bytes to fill read in a single transaction. Read more
Source§

impl<Dm: DriverMode> I2c for I2c<'_, Dm>

Source§

fn transaction( &mut self, address: u8, operations: &mut [Operation<'_>], ) -> Result<(), Self::Error>

Execute the provided operations on the I2C bus. Read more
Source§

fn read(&mut self, address: A, read: &mut [u8]) -> Result<(), Self::Error>

Reads enough bytes from slave with address to fill read. Read more
Source§

fn write(&mut self, address: A, write: &[u8]) -> Result<(), Self::Error>

Writes bytes to slave with address address. Read more
Source§

fn write_read( &mut self, address: A, write: &[u8], read: &mut [u8], ) -> Result<(), Self::Error>

Writes bytes to slave with address address and then reads enough bytes to fill read in a single transaction. Read more
Source§

impl InterruptConfigurable for I2c<'_, Blocking>

Available on crate feature unstable only.

§Stability

This API is marked as unstable and is only available when the unstable crate feature is enabled. This comes with no stability guarantees, and could be changed or removed at any time.

Source§

fn set_interrupt_handler(&mut self, handler: InterruptHandler)

Registers an interrupt handler for the peripheral on the current core. Read more
Source§

impl<Dm: DriverMode> SetConfig for I2c<'_, Dm>

Available on crate feature unstable only.

§Stability

This API is marked as unstable and is only available when the unstable crate feature is enabled. This comes with no stability guarantees, and could be changed or removed at any time.

Source§

type Config = Config

The configuration type used by this driver.
Source§

type ConfigError = ConfigError

The error type that can occur if set_config fails.
Source§

fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError>

Set the configuration of the driver.

Auto Trait Implementations§

§

impl<'d, Dm> Freeze for I2c<'d, Dm>

§

impl<'d, Dm> RefUnwindSafe for I2c<'d, Dm>
where Dm: RefUnwindSafe,

§

impl<'d, Dm> Send for I2c<'d, Dm>
where Dm: Send,

§

impl<'d, Dm> Sync for I2c<'d, Dm>
where Dm: Sync,

§

impl<'d, Dm> Unpin for I2c<'d, Dm>
where Dm: Unpin,

§

impl<'d, Dm> UnsafeUnpin for I2c<'d, Dm>

§

impl<'d, Dm> !UnwindSafe for I2c<'d, Dm>

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.