2020年5月23日 星期六

四.5 I2C介面元件位址偵測實習


前一個範例中示範了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:回應正常,有明確的裝置連接在這個位址上。

2error=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


沒有留言:

張貼留言