2011-08-20

兩部Arduino之間的I2C通訊



Arduino I2C通訊使用A4(SDA)A5(SCL)兩個腳位,API library則是<Wire.h>

兩部Arduino之間的I2C通訊,需要有一方擔任Master負責主控資料通訊,另一方擔任Slave負責接收及回應來自Master的需求,而Master是依據SlaveI2C 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),像MindsensorsHiTechnic裝置的手冊都是8-bits定址,還好是如果使用<NXTI2CDevice.h>會處理掉定址問題。

不過,如果將Arduino作為I2C SlaveNXT作為I2C Master,定址問題就很重要。






Arduino to Arduino I2C通訊線路接線




兩部Arduino之間的I2C通訊接線方式除了連接兩方的SDA(A4)SCL(A5)之外,還須對這兩條線加pull-up,我是使用4.7k歐姆,另外還須要common
ground
,總之就是要確保電壓準位。


以下就是接線圖:








而測試案例則以Slave Arduino模擬NXTI2C 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);          




}









沒有留言:

張貼留言