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.
91 lines
2.4 KiB
Arduino
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);
|
|
}
|