Arduino教程-10. 內部積體電路(I2C)
Arduino 內部積體電路
通訊介面I2C
I2C介面的原意是"Inter IC",只用兩條線來連線其他元件,為了方便同一個電路板上的各個元件相互通訊。
I2C至少有一個主控端(master,通常由微處理器擔任,負責傳送時鐘和地址訊號)和至少一個從端(slave,通常是感測器元件),所有I2C元件的資料線和時鐘線都連線在一起。此外,I2C的資料線和時鐘線都要連線一個電阻到電源線,電阻值通常選擇1~10KΩ,建議採用1.8kΩ。每個I2C元件的接地線必須相連。為了識別電路板上的不同元件,每個I2C從端都有一個唯一的地址編號。地址編號的長度為7位,總共可以表示27個地址(127個),
內部積體電路(I2C)是用於微控制器和新一代專用積體電路之間的序列資料交換系統。當它們之間的距離很短(接收器和發射器通常在同一個印刷電路板上)時使用。通過兩根導線建立連線。一個用於資料傳輸,另一個用於同步(時鐘訊號)。
如下圖所示,一個裝置始終是主裝置。它在通訊開始之前執行一個從晶片的定址。這樣,一個微控制器可以與112個不同的裝置進行通訊。波特率通常為100 Kb/sec(標準模式)或10 Kb/sec(慢波特率模式)。最近出現了波特率為3.4 Mb/s的系統。通過I2C匯流排通訊的裝置之間的距離限制在幾米之內。
板的I2C引腳
I2C匯流排由兩個訊號組成 - SCL和SDA。SCL是時鐘訊號,SDA是資料訊號。當前匯流排主機總是產生時鐘訊號。一些從裝置可能迫使時鐘低電平以延遲主裝置傳送更多資料(或者在主設備嘗試將資料寫出之前請求更多的時間來準備資料)。這被稱為“時鐘伸展”。
以下是不同Arduino板的引腳:
- Uno, Pro Mini A4 (SDA), A5 (SCL)
- Mega, Due 20 (SDA), 21 (SCL)
- Leonardo, Yun 2 (SDA), 3 (SCL)
Arduino I2C
我們有兩種模式 - 主程式碼和從程式碼 - 使用I2C連線兩個Arduino板。它們是:
- Master Transmitter / Slave Receiver 主發射器/從接收器
- Master Receiver / Slave Transmitter 主接收器/從發射器
主發射器/從接收器
讓我們現在看看什麼是主傳送器和從接收器。
主發射器
以下函式用於初始化Wire庫,並將I2C匯流排作為主器件或從器件加入。這通常只被呼叫一次。
- Wire.begin(地址) - 在我們的例子中,地址是7位從地址,因為未指定主機,它將作為主機加入匯流排。
- Wire.beginTransmission(地址) - 開始向給定地址的I2C從裝置傳送資料。
- Wire.write(值) - 用於從主裝置傳輸到從裝置的佇列位元組(在beginTransmission()和endTransmission()之間的呼叫)。
- Wire.endTransmission() - 結束由beginTransmission()開始的對從裝置的傳輸,並傳輸由wire.write()排隊的位元組。
示例
#include <Wire.h> //include wire library
void setup() //this will run only once {
Wire.begin(); // join i2c bus as master
}
short age = 0;
void loop() {
Wire.beginTransmission(2);
// transmit to device #2
Wire.write("age is = ");
Wire.write(age); // sends one byte
Wire.endTransmission(); // stop transmitting
delay(1000);
}
從接收器
使用以下函式:
-
Wire.begin(地址) - 地址是7位從地址。
-
Wire.onReceive(收到的資料處理程式) - 當從裝置從主裝置接收資料時呼叫的函式。
-
Wire.available() - 返回Wire.read()可用於檢索的位元組數,應在Wire.onReceive()處理程式中呼叫。
示例
#include <Wire.h> //include wire library
void setup() { //this will run only once
Wire.begin(2); // join i2c bus with address #2
Wire.onReceive(receiveEvent); // call receiveEvent when the master send any thing
Serial.begin(9600); // start serial for output to print what we receive
}
void loop() {
delay(250);
}
//-----this function will execute whenever data is received from master-----//
void receiveEvent(int howMany) {
while (Wire.available()>1) // loop through all but the last {
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
}
主接收器/從發射器
讓我們現在看看什麼是主接收器和從發射器。
主接收器
主機被程式設計為請求,然後讀取從唯一定址的從機Arduino傳送的資料位元組。
使用以下函式:
- Wire.requestFrom(地址,位元組數) - 主裝置用於請求從裝置的位元組。然後可以使用函式- wire.available()和wire.read()檢索位元組。
示例
#include <Wire.h> //include wire library void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}
void loop() {
Wire.requestFrom(2, 1); // request 1 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);
}
從發射器
使用以下函式:
- Wire.onRequest(處理程式) - 當主裝置從此從裝置請求資料時呼叫該函式。
示例
#include <Wire.h>
void setup() {
Wire.begin(2); // join i2c bus with address #2
Wire.onRequest(requestEvent); // register event
}
Byte x = 0;
void loop() {
delay(100);
}
// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
Wire.write(x); // respond with message of 1 bytes as expected by master
x++;
}