The I2C, or Wire as it is called in the world of Arduino, is a two wire serial bus that allow many master and slave devices to communicate with each other over the same bus. It is therefore an efficient way to connect many devices using only two wires. Each device has its own address that is used when communicating with the device. Many ICs and also units, e.g. some LCDs, communicate via I2C. The I2C bus can run at 100 kHz (default) or 400 kHz.
The RFzero has an internal I2C bus that is used by the EEPROM and Si5351A exclusively. The internal I2C bus is automatically initialized when the RFzero.init() function is called.
But there is also an I2C user bus available on D8 (SDA) and D9 (SCL) on the JP11 connector. The below program shows how to use the RFzero I2C user bus connected to a Semtech SX1509 port expander. The principle is the same for the default I2C bus on the Arduino Zero and Arduino M0 boards.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
// RFzero include and object creation #include <RFzero.h> // MUST ALWAYS be included for RFzero int SX1509_ReadByte(byte devAddr, byte regAddr) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); Wire.requestFrom(devAddr, (byte) 1); int millisStart = millis(); while ((!Wire.available()) && (millis() - millisStart < 5)); // Wait max 5 ms for data if (Wire.available()) return Wire.read(); else return -1; } void SX1509_WriteByte(byte devAddr, byte regAddr, byte value) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.write(value); Wire.endTransmission(); } void setup() { // USB initialize SerialUSB.begin(9600); // Initialize the I2C/Wire Wire.begin(); // Start the I2C user bus/default bus at 100 kHz Wire.setClock(400000); // Change the speed, if needed. Otherwise line can be omitted // Reset the SX1509 just in case SX1509_WriteByte(0x3E, 0x7D, 0x12); // Reset the SX1509 SX1509_WriteByte(0x3E, 0x7D, 0x34); // See datasheet table 14 // Set I/O directions SX1509_WriteByte(0x3E, 0x0F, 0x00); // Set I/O 7 to 0/RegA as output SX1509_WriteByte(0x3E, 0x0E, 0xFF); // Set I/O 15 to 7/RegB as input SX1509_WriteByte(0x3E, 0x06, 0xFF); // Enable pull-up on I/O 15 to 7/RegB } void loop() { // Flash outputs 250 ms on and 250 ms off interlaced SX1509_WriteByte(0x3E, 0x11, 0x55); delay(250); SX1509_WriteByte(0x3E, 0x11, 0xAA); delay(250); // Read the input and print on the USB port int input = SX1509_ReadByte(0x3E, 0x10); if (input == -1) SerialUSB.println("No data available"); else SerialUSB.println(input, HEX); } |
If you want to use the above example on your Arduino Zero or Arduino M0 default I2C/Wire pins please note that the pins don’t match directly with the RFzero as the below table shows.
I2C signal | RFzero Pin/Port | Arduino Zero or M0 pins |
---|---|---|
SDA | D8/PA16 | SDA/PA22 |
SCL | D9/PA17 | SCL/PA23 |
Don’t forget to connect the pull-up resistors on the RFzero too, 4,7 kΩ to 10 kΩ will work in most cases.
Please note that if your I2C device(s) use 5 V you will need a 3,3 V to/from 5 V level converter that can be made either by discrete components, ready made board or an IC. Please see the Third party accessories section on the Shop page.
For more information about the I2C bus please see the application report from Texas Instruments: Understanding the I2C Bus.