前一個範例中示範了I2C介面的LCD顯示器使用方法,在I2C匯流排的SCL與SDA這兩條線上,可以同時並接許多相同或不同的裝置在上面,只要這些裝置使用不同的通訊位址即可。不過有使用過I2C介面元件或裝置的使用者可能經常會遇到一個問題,就是買到的元件到底使用的通訊位址為何﹖以前一個範例所使用的I2C介面LCD顯示器來說,並沒有一個統一的通訊位址,因此在購賣時一定要先跟廠商確認;可是販售的廠商有時候也不一定知道,或是給了錯誤的資料,這樣一來讓使用者增加許多的困擾。
為了解決這個困擾,特地設計這個可以得知在並接在I2C匯流排之SCL與SDA這兩條線上所有裝置所使用的通訊位址的範例程式。由於現在許多使用I2C匯流排的元件或裝置並沒有依循最初飛利浦公司所訂定的種類、名稱與分配的位址,所以在此範例中只會顯示所有並接元件或裝置的位址,無法列出其名稱;為了避免有些元件使用了相同的位址,如果想要測試你手上元件的通訊位址,最好一次只連接一個元件去測試,這樣才能正確無誤的找到它們所使用的位址。
◎功能與動作說明:
1、 測試所有並接在ESP8266的I2C介面匯流排上元件或裝置的位址,並且將這些的位址顯示在Arduino IDE的序列監控視窗上。
2、 在Arduino IDE的序列監控視窗中只顯示所使用的位址,不會顯示元件或裝置的名稱,而且不會測試是否使用到相同的位址。
◎ 電路圖:
◎程式說明與列表:
之前說過I2C匯流排介面在Arduino IDE系統中是屬於”Wire.h”這個程式庫,所以必須先引入宣告,只是這個程式庫是內建在Arduino IDE系統中的程式庫路徑內,所以我們不必特別去下載安裝。
1 #include <Wire.h> // 引入兩線式元件的程式庫
接著在初始化(setup())程式區中先以”Wire.begin()”這個指令啟動程式庫,及設定Arduino IDE的序列監控視窗傳輸速率為115200bps,並先傳送”I2C Scanner..”這個提示訊息到Arduino IDE序列監控視窗上,告訴使用者程式將開始掃描連接在I2C匯流排上元件的位址。
5 Wire.begin(); // 啟動"Wire"功能
6 Serial.begin(115200); // 啟動序列通訊功能,設定傳輸速率為115200bps
7 Serial.println("\nI2C Scanner..");
至於主迴圈(loop())程式一開始先定義一些程式會用到的變數:
14 byte error,I2C_address;
15 int nDevices=0;
然後每隔5秒以輪流詢問的方去掃描連接在I2C匯流排上元件,如果有回應便代表有元件或裝置連接在這個的位址上。目前在I2C匯流排上元件可使用的位址是在1~127(或16進制的0x00~0xff),所以整個輪詢掃描的動作是由19~39行的”for”迴圈所構成。在迴圈中「I2C_address」這個變數是迴圈計數值,也是被測元件的位址,因此下面兩行程式會按照「I2C_address」所指定的位置送出查詢訊息,並由「error」這個變數接收查詢的結果。
21 Wire.beginTransmission(I2C_address); // 送出指定位址的查詢訊息
22 error=Wire.endTransmission(); // 由變數"error"接收傳送結果
依”Wire.h”這個程式庫的規定,「error」這個裝置回應變數的值有三種可能:
1、 error=0:回應正常,有明確的裝置連接在這個位址上。
2、 error=4:回應正常,有裝置連接在這個位址上,但裝置種類不明。
3、 其他:回應異常,代表沒有裝置連接在這個位址上。
因此迴圈中後續的程式便是依照「error」這個變數的三種結果做出不同的回應。如果error=0代表裝置回應正常,程式會將該裝置的位址以16進制的格式顯示在Arduino IDE序列監控視窗中,其內容下:
“I2C device found at address 0x??”
其中的”??”是這個裝置的位址值,而且把「nDevices」這個代表測試成功的裝置數目變數值加一(23~31行);如果error=4代表裝置有回應,但是裝置種類不明,則程式會回應下列的訊息:
“Unknow error at address 0x??”
假如「error」這個變數是其他的值,代表這個被測試的位址沒有任何裝置回應,那麼就繼續下一個位址的測試,直到迴圈全結束為止。
在for迴圈執行完一遍之後,由「nDevices」這個變數就可以得知一共有多少個明確的裝置並接在測試的I2C匯流排上,如果裝置的數目為0,則程式(41行)會送出下列的訊息到Arduino IDE序列監控視窗:
"No I2C devices found!\n"
反之則送出”Done!”作為結束,並且在等待5秒後再次重新開始for的測試迴圈。
以下是完整的程式列表:
#include <Wire.h> // 引入兩線式元件的函式庫
void setup()
{
Wire.begin(); // 啟動"Wire"功能
Serial.begin(115200); // 啟動序列通訊功能,設定傳輸速率為115200bps
Serial.println("\nI2C Scanner..");
delay(1000);
}
void loop()
{
byte error,I2C_address;
int nDevices=0;
Serial.println("Scanning address start!");
// 以for()迴圈的方式去輪詢I2C線上的裝置
for(I2C_address=1;I2C_address<127;I2C_address++)
{ // 裝置的位址由1~127
Wire.beginTransmission(I2C_address); // 送出指定位址的查詢訊息
error=Wire.endTransmission(); // 由變數"error"接收傳送結果
if(error==0) // error=0 代表有裝置回應
{
Serial.print("I2C device found at address 0x");
if(I2C_address<16)
Serial.print("0"); // 若裝置位址<16則在前面補一個'0'
Serial.println(I2C_address,HEX); // 以16進制的方式顯示I2C線上裝置的位址值
nDevices++; // 裝置數變數值加1
}
if(error==4) // error=4 代表裝置不明
{
Serial.print("Unknow error at address 0x");
if(I2C_address<16)
Serial.print("0");
Serial.println(I2C_address,HEX);
}
}
if(nDevices==0) // 裝置數變數值=0代表線上沒有任何裝置
Serial.println("No I2C devices found!\n");
else
Serial.println("Done!\n");
delay(5000);
}
程式名稱:I2C_Address.ino
沒有留言:
張貼留言