原理圖:
圖 I2C介面的RTC晶片
圖 微控制器I2C部分引腳圖
軟體
啟動I2C
啟動Wire庫並作為主機或者從機加入匯流排,這個函式呼叫一次即可,引數為7位從機地址,不帶引數就以主機的形式加入匯流排。
Wire.begin();
Wire.begin(address);
主裝置從從裝置請求位元組
由主裝置向從裝置請求位元組,之後用available()和read()函式讀取位元組,第三個引數位為stop,在請求後會傳送停止訊息,釋放I2C匯流排,否則匯流排就不會被釋放。
Wire.requestFrom(address, quantity);
Wire.requestFrom(address, quantity, stop);
給指定地址的從裝置傳輸資料
給指定地址的從裝置傳輸資料,之後呼叫write()函式排隊傳輸位元組,要透過endTransmission()
結束傳輸。
Wire.beginTransmission(address)
endTransmission()
有以下幾個返回結果:
-
0:成功
-
1:資料太長,無法放入傳送緩衝區
-
2:在傳送地址時收到 NACK
-
3:在傳送資料時收到 NACK
-
4:其他錯誤
寫資料
向從裝置寫入資料,在呼叫 beginTransmission()
和 endTransmission()
之間。
Wire.write(value)
Wire.write(string)
Wire.write(data, length)
舉個例子
#include <Wire.h>
byte val = 0;
void setup()
{
Wire.begin(); // join i2c bus
}
void loop()
{
Wire.beginTransmission(44); // transmit to device #44 (0x2c)
// device address is specified in datasheet
Wire.write(val); // sends value byte
Wire.endTransmission(); // stop transmitting
val++; // increment value
if(val == 64) // if reached 64th position (max)
{
val = 0; // start over from lowest value
}
delay(500);
}
讀資料
呼叫requestFrom()後從從裝置讀取資料。
Wire.read()
舉個例子
#include <Wire.h>
void setup(){
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}
void loop(){
Wire.requestFrom(2, 6); // request 6 bytes from slave device #2
while(Wire.available()) // slave may send less than requested
{
char c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
}
delay(500);
}
還有其它一些函式,例如修改時脈頻率等等,大家用到的時候自行了解一下。
完整程式
這裡我們用一個例子來演示一下,I2C啟動之後,我們開始掃描匯流排上存在的裝置,並透過串列埠列印結果出來,我在I2C下面接了一個OLED的裝置。
#include "Wire.h"
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println("Scanning for I2C Devices ...");
Serial.print("\r\n");
int I2CDevices = 0;
byte address;
Wire.begin();
for (address = 1; address < 127; address++)
{
Wire.beginTransmission(address);
if (Wire.endTransmission() == 0) //傳送成功
{
Serial.print("Found I2C Device: ");
Serial.print(" (0x");
if (address < 16)
{
Serial.print("0");
}
Serial.print(address, HEX);
Serial.println(")");
I2CDevices++;
}
}
if (I2CDevices == 0)
{
Serial.println("沒有發現I2C裝置!\n");
}
else
{
Serial.print("發現了");
Serial.print(I2CDevices);
Serial.println("個I2C裝置!\n");
}
}
void loop()
{
}
Wire.endTransmission()
返回0,代表這個地址通訊成功,我們就認為匯流排上存在這個地址的裝置。