Arduino I2C通訊使用A4(SDA)與A5(SCL)兩個腳位,API library則是<Wire.h>。
兩部Arduino之間的I2C通訊,需要有一方擔任Master負責主控資料通訊,另一方擔任Slave負責接收及回應來自Master的需求,而Master是依據Slave在I2C Bus中的位址來傳送與要求回應資料。
在<Wire.h>中Slave Arduino使用begin(address)來宣告加入I2C bus的位址,之後Master Arduino就可以使用:
(1) beginTransmission(address)+send(data)+endTransmission()傳送資料至Slave Arduino。
(2) requestFrom(address,count)
向Slave Arduino要求回應資料。
Slave Arduino處理來自Master
Arduino的資料通訊需求是透過:
(1) 以onReceive(handler) 註冊處理當接收到來自Master Arduino send(data)所傳送資料時會觸發的處理程序(handler)。
(2) 以onRequest(handler) 註冊處理當接收到來自Master Arduino requestFrom(address,count)要求回應資料時會觸發的處理程序(handler)。
I2C bus address
<Wire.h>使用7-bits定址,參考有些I2C裝置在data sheet所載其實是8-bits定址,所以呼叫<Wire.h>函數時須要右移一個bit(除以2),像Mindsensors與HiTechnic裝置的手冊都是8-bits定址,還好是如果使用<NXTI2CDevice.h>會處理掉定址問題。
不過,如果將Arduino作為I2C Slave而NXT作為I2C Master,定址問題就很重要。
Arduino to Arduino I2C通訊線路接線
兩部Arduino之間的I2C通訊接線方式除了連接兩方的SDA(A4)與SCL(A5)之外,還須對這兩條線加pull-up,我是使用4.7k歐姆,另外還須要common
ground,總之就是要確保電壓準位。
以下就是接線圖:
而測試案例則以Slave Arduino模擬NXT的I2C register layout,由Master Arduino讀取其裝置資訊
Slave Arduino程式
#include
<Wire.h>
#define I2C_SLAVE_ADDRESS 0x31
uint8_t softwareVersion[9] =
"V1.00 ";
uint8_t vendorID[9] = "Arduino
";
uint8_t deviceID[9= "UNO ";
byte requestRegister;
void setup()
{
Wire.begin(I2C_SLAVE_ADDRESS);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
}
void loop() { }
void receiveEvent(int howMany)
{
requestRegister = Wire.receive();
}
void requestEvent()
{
if (requestRegister == 0x00) {
Wire.send(softwareVersion, 8);
}
else if (requestRegister == 0x08) {
Wire.send(vendorID, 8);
}
else if (requestRegister == 0x10) {
Wire.send(deviceID, 8);
}
}
Master端程式
#include
<Wire.h>
const byte ARDUINO_SLAVE= 0x31;
const byte SOFTWARE_VERSION = 0x00;
const byte VENDOR_ID= 0x08;
const byte DEVICE_ID= 0x10;
const byte NUM_OF_BYTES= 8;
void setup()
{
Serial.begin(9600);
Wire.begin();
}
void loop()
{
requestFromSlave(SOFTWARE_VERSION);
delay(1000);
requestFromSlave(VENDOR_ID);
delay(1000);
requestFromSlave(DEVICE_ID);
delay(1000);
}
void requestFromSlave(const byte
slaveRegister)
{
byte nbytesReady= 0;
char strBuffer[9] = "
";
Wire.beginTransmission(ARDUINO_SLAVE);
Wire.send(slaveRegister);
Wire.endTransmission();
Wire.requestFrom(ARDUINO_SLAVE, NUM_OF_BYTES);
nbytesReady = Wire.available();
for (byte xi=0;
xi
strBuffer[xi] = Wire.receive();
Serial.println(strBuffer);
}
沒有留言:
張貼留言