1. I2C bus marked as SDA/SCL on the header pins works well with Wire.h Library and Wire.begin(). In both STM and Arduino documentation Fig-1), it is shown as I2C2. I have tested the functionality of the bus using I2C Slave Address Scanner Sketch (4.) and MCP4725 DAC (Fig-2). The DAC is found at correct slave address 0x60. The DAC breakout board contains 2x4.7k pull-up resistors.
2. Arduino documentation (Fig-1 below) has shown another I2C3_SDA/SCL bus as alternate function of A4/A5. I have connected the DAC at this bus and ran the scanner sketch, but I could not find its presence on the bus with Wire.h and Wire.begin()/Wire1.begin()/Wire2.begin(). (Wire3.begin() is not accepted.)
3. I could not check I2C4 bus due to lack of Qwiic connector.
4. This is the I2C Slave Address Scanner Sketch:
#include<Wire.h>
byte busStatus;
void setup()
{
Serial.begin(9600);
Wire.begin();
for (int i2cAddress = 0x00; i2cAddress <= 0x7F; i2cAddress++)
{
Wire.beginTransmission(i2cAddress);
busStatus = Wire.endTransmission();
if (busStatus == 0x00)
{
Serial.print("I2C Device found at address: 0x");
Serial.println(i2cAddress, HEX);
}
else
{
Serial.print("I2C Device not found at address: 0x");
Serial.println(i2cAddress, HEX);
}
}
}
void loop()
{
}
Although physically routed, for some reason pins A4 and A5 are not mapped to and I2C function within the Arduino Zephyr core. I2C3 can apparently be made available by modifying the core overlay and creating a variant, which will require messing with the core files. Perhaps someone will be able to share the details of how this can be done. Unless there is a spacific reason for needing to use pins A4/A5, it might be less hassle to just use the QWIIC port or the header pins that you have already identified as being functional.
Now, I know from the forum members that there are no simple Arduino APIs to activate the I2C3 bus on A4/A5 pin like Serial1.begin() API which activates a functional UART Port on D0/D1 pins on the header.
Being inspired by Srerial1.begin() API, I have thought that the simple Wire3.begin() will activate the I2C3 bus; but, it is NOT.
Think you misunderstand. Wire2 has been available for the last couple of releases. To "activate" it just use Wire2.begin and now you can use A4/A5 as Wire2.
Just to show more info if you look at the pinout you see A4/A5 as PC1/PC0
Your wire scanner test is hard coded to Wire. That is you not only need to have Wire2.begin, you also need to change the other references to Wire2 as well.
Something like:
#include<Wire.h>
byte busStatus;
void setup()
{
Serial.begin(9600);
Wire2.begin();
for (int i2cAddress = 0x00; i2cAddress <= 0x7F; i2cAddress++)
{
Wire2.beginTransmission(i2cAddress);
busStatus = Wire2.endTransmission();
if (busStatus == 0x00)
{
Serial.print("I2C Device found at address: 0x");
Serial.println(i2cAddress, HEX);
}
else
{
Serial.print("I2C Device not found at address: 0x");
Serial.println(i2cAddress, HEX);
}
}
}
void loop()
{
}
Nice update @KurtE - that makes it easier. Not sure why you have sdram test included - looks like something I do.
Just to let you know about the wire scanner we use - its based off of something we have been using on the Teensy for years and besides printing out device addresses it will also print out device name if its in the list of devices, i.e.,
void printKnownChips(byte address)
{
// Is this list missing part numbers for chips you use?
// Please suggest additions here:
// https://github.com/PaulStoffregen/Wire/issues/new
switch (address) {
case 0x00: Serial.print(F("AS3935")); break;
case 0x01: Serial.print(F("AS3935")); break;
case 0x02: Serial.print(F("AS3935")); break;
case 0x03: Serial.print(F("AS3935")); break;
case 0x04: Serial.print(F("ADAU1966")); break;
case 0x0A: Serial.print(F("SGTL5000")); break; // MCLK required
case 0x0B: Serial.print(F("SMBusBattery?")); break;
case 0x0C: Serial.print(F("AK8963")); break;
case 0x10: Serial.print(F("CS4272, BMM150")); break;
case 0x11: Serial.print(F("Si4713")); break;
case 0x13: Serial.print(F("VCNL4000,AK4558")); break;
case 0x18: Serial.print(F("LIS331DLH")); break;
case 0x19: Serial.print(F("LSM303,LIS331DLH")); break;
case 0x1A: Serial.print(F("WM8731")); break;
.....
Of you course if device is not listed you can always add it.
Why is it like this in the following table? I mean that hardware bus name does not do one-to-one orrespondance with sofware object name. I2C3 has the object named Wire2 and not Wire3; I2C3 has the object amed Wire2. Where is the I2C1?
Object -------------> Wire Wire1 Wire2 Wire3 Wire4
Bus
|
|
v
I2C1
I2C2 (SDA/SCL) ------ x
I2C3 (A4/A5) ---------------------------- x
I2C4 (QWIIC) ------------------- x
Ok now you getting down into the guts of the STM32 processor itself and how you go from manufacturers reference manual to actual implementation.
Essentially, n Zephyr, the names you see in a device tree overlay such as &i2c3 do not necessarily match the physical Arduino header names. They refer to the MCU's internal peripheral instance numbering. From the reference manual (section 65) you will see the i2c numbering on the processor
Basically what you seeing when you look at the board overlay and if you dive down deeper the dts file in zephyr for the Q is the mapping from the MCU through to the Arduino environment.
What the Wire library does as well as the core is an abstraction layer from the Zephyr to Arduino which we are all useful.
Hope this helps somewhat. Probably could write a book on this but not fully qualified for that - hopefully someone will jump in and explain more.