Skip to content

Latest commit

 

History

20 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

I2C slave protocol for multiple addresses on RP2040

This library implements an I2C slave protocol for the RP2040 using PIO, with support for responding to multiple I2C addresses.

It is compatible with both the Pico SDK and Arduino-Pico.

Features

  • I2C slave implemented in PIO
  • Supports multiple I2C addresses
  • Compatible with Pico SDK and Arduino
  • Optional receive, request, and stop handlers
  • Supports fixed-length transfers for compatibility with buggy I2C masters
  • Supports standard I2C speeds up to 1 MHz
  • Uses one full PIO instance

High-speed operation

The library has been tested beyond standard I2C speeds.

Operation at 2 MHz has been verified, but timing margins become very small, especially with back-to-back transactions and the stop callback enabled. Speeds above 1 MHz should therefore be considered experimental.

Usage

Pico SDK

Add the following files to your project:

  • i2c_multi.pio
  • i2c_multi.h
  • i2c_multi.c

Then update your CMakeLists.txt to:

  • call pico_generate_pio_header
  • link the required libraries:
    • pico_stdlib
    • hardware_irq
    • hardware_pio
    • hardware_i2c

See sdk/CMakeLists.txt for an example.

Arduino

Add the following files to your project:

  • i2c_multi.pio.h
  • i2c_multi.h
  • i2c_multi.c

Basic setup

  • Define the receive, request, and stop handlers if needed
  • Set the write buffer pointer
  • Enable the I2C addresses you want to use for communication

Hardware notes

Use pull-up resistors from 1 kΩ to 3.3 kΩ.
Use lower resistor values for higher bus speeds.

See sdk/main.c for a usage example.


RP2040 configured as an I2C slave (left), receiving and sending data through multiple I2C addresses from an I2C master (right)

API reference

void i2c_multi_init(pio, pin)

Must be called first.

Parameters

  • pio - PIO instance where the program will be loaded (pio0 or pio1)
  • pin - SDA pin number; SCL is assigned to pin + 1

void i2c_multi_set_receive_handler(i2c_receive_handler_t i2c_receive_handler)

Sets the receive handler.

Parameters

  • i2c_receive_handler - function called when data or an address is received

void i2c_multi_set_request_handler(i2c_request_handler_t i2c_request_handler)

Sets the request handler.

Parameters

  • i2c_request_handler - function called when the master requests data

void i2c_multi_set_stop_handler(i2c_stop_handler_t i2c_stop_handler)

Sets the stop handler.

Parameters

  • i2c_stop_handler - function called when a STOP condition is detected

void i2c_multi_set_write_buffer(uint8_t \*buffer)

Sets the write buffer.

Parameters

  • buffer - write buffer

void i2c_multi_disable(void)

Puts I2C on hold by disabling the PIO state machines.


void i2c_multi_restart(void)

Restarts the PIO state machines and resets the byte counter.


void i2c_multi_remove(void)

Removes the PIO state machines and clears handlers, write buffer, and byte counter.


void i2c_multi_enable_address(uint8_t address)

Enables one I2C address.

Parameters

  • address - I2C address to enable

void i2c_multi_disable_address(uint8_t address)

Disables one I2C address.

Parameters

  • address - I2C address to disable

void i2c_multi_enable_all_addresses(void)

Enables all I2C addresses.


void i2c_multi_disable_all_addresses(void)

Disables all I2C addresses.


bool i2c_multi_is_address_enabled(uint8_t address)

Checks whether an I2C address is enabled.

Parameters

  • address - I2C address to check

Returns

  • true if the address is enabled
  • false otherwise

void i2c_multi_fixed_length(int16_t length)

Releases the bus after the specified number of bytes has been sent.
Useful for compatibility with buggy I2C masters.

Handler callbacks

void receive_handler(uint8_t data, bool is_address)

Called when a byte or address is received.

Parameters

  • data - received byte or address
  • is_address - true if data is an address, false if it is a data byte

void request_handler(uint8_t address)

Called when the master requests data.

Parameters

  • address - I2C address used in the request

void stop_handler(uint8_t length)

Called when a STOP condition is detected.

Parameters

  • length - number of bytes received or sent

Remark

I2C callbacks run in interrupt context and should be kept short and non-blocking. This is especially critical for the stop callback, since a STOP condition releases the bus and the next transaction may start immediately.

Avoid printf, Serial, delays, or other slow operations inside the stop callback, particularly with back-to-back transactions. If debug output is required, store the data in the callback and print it later from the main loop.

Changelog

  • Fixed repeated START support and documented timing considerations for stop callbacks and high-speed/back-to-back transactions.
  • PIO program size increased to 30 instructions
  • Reduced from 32 to 28 PIO instructions
  • Improved high-speed operation
  • Added i2c_multi_fixed_length() to release the bus after a fixed number of bytes
  • Initial release

About

I2C slave protocol to answer to multiple addresses for the RP2040

Topics

Resources

Stars

32 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages