Files
earlephilhower_arduino-pico/libraries/Wire/examples/TalkingToMyselfAsync/TalkingToMyselfAsync.ino
T
Earle F. Philhower, III 11814823ed Add asynchronous I2C read and write operations (#2167)
Fixes #1730

Uses DMA operations to avoid the need to bit-bang or busy wait for I2C operations
that might be very slow.  Optional, adds new API calls to enable.  Simple example
included.
2024-05-21 14:32:12 -07:00

91 lines
2.4 KiB
Arduino

// Simple asynchronous I2C master and slave demo - Earle F. Philhower, III
// Released into the public domain.
//
// Using both onboard I2C interfaces, have one master and one slave
// and send data both ways between them.
//
// Uses the async Wire calls to allow applications to do other work while
// I2C transactions are ongoing.
//
// To run, connect GPIO0 to GPIO2, GPIO1 to GPIO3 on a single Pico
#include <Wire.h>
void setup() {
Serial.begin(115200);
delay(5000);
Wire.setSDA(0);
Wire.setSCL(1);
Wire.begin();
Wire1.setSDA(2);
Wire1.setSCL(3);
Wire1.begin(0x30);
Wire1.onReceive(recv);
Wire1.onRequest(req);
}
static char buff[100];
void loop() {
static int p;
char b[90];
int loops;
// Write a value over I2C to the slave
Serial.println("\n\nSending...");
sprintf(b, "This buffer is larger than the I2C FIFO by a whole lot, Pass #%d", p++);
Wire.writeAsync(0x30, b, strlen(b), true);
// A real application would go do some useful work here and check the
// finishedAsync value when it needs the I2S operation to be completed
// Here' we'll just increment a counter to show how much work could be done...
loops = 0;
while (!Wire.finishedAsync()) {
loops++;
}
Serial.printf("Write idle loops: %d\n", loops);
// Ensure the slave processing is done and print it out
delay(1000);
Serial.printf("buff: '%s'\n", buff);
Serial.printf("Receiving...\n");
// Read from the slave and print out
bzero(b, sizeof(b));
Wire.readAsync(0x30, b, 73, true);
loops = 0;
while (!Wire.finishedAsync()) {
loops++;
}
Serial.printf("Read idle loops: %d\n", loops);
Serial.print("recv: '");
for (int i = 0; i < 73; i++) {
Serial.print(b[i]);
}
Serial.println("'");
delay(1000);
}
// These are called in an **INTERRUPT CONTEXT** which means NO serial port
// access (i.e. Serial.print is illegal) and no memory allocations, etc.
// Called when the I2C slave gets written to
void recv(int len) {
int i;
// Just stuff the sent bytes into a global the main routine can pick up and use
for (i = 0; i < len; i++) {
buff[i] = Wire1.read();
}
buff[i] = 0;
}
// Called when the I2C slave is read from
void req() {
static int ctr = 765;
char buff[100];
// Return a simple incrementing hex value
sprintf(buff, "Slave responds with a message that's longer than FIFO as well, id #%06X", (ctr++) % 65535);
Wire1.write(buff, 73);
}