【esp32 專案】使用I2C

FBshark發表於2024-06-11

原理圖:

【esp32 專案】使用I2C

圖 I2C介面的RTC晶片

【esp32 專案】使用I2C

圖 微控制器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,代表這個地址通訊成功,我們就認為匯流排上存在這個地址的裝置。

【esp32 專案】使用I2C

相關文章