# ESP32 I2C積體匯流排電路 :::info #### 何謂I2C? ##### I2C(Inter-Integrated Circuit),它是一種串列通訊匯流排,使用多主從架構進行晶片與晶片之間的短距離通訊。在通訊的過程中,每個Slave晶片中都會有相對應的7bit的地址讓Master來辨別晶片的身分,是否為通訊目標,並選擇該晶片進行資料傳輸。 ::: ## **I2C架構** ![](https://hackmd.io/_uploads/SJgDF5hCn.png) ###### ESP32 為 Master時,可藉由I2C與其他Slave裝置進行短距離通訊 :::info ### I2C以SDA和SCL兩種訊號來進行資料傳輸 * ### SDA: #### SDA為I2C之串列資料線(SDA),Master可藉由SDA資料線讀取其他Slave的資料或者是寫入資料到其他Slave晶片中。 * ### SCL: #### SCL為串列時鐘線,Master藉由SCL提供I2C-Bus時脈訊號。 ::: ![](https://hackmd.io/_uploads/ryfDHc20h.png) --- ## **ESP32 I2C Driver** ### **ESP32 I2C驅動安裝流程** ![](https://hackmd.io/_uploads/BJ6SljhC3.png) ### 1. **參數配置** :::info #### ESP32在執行I2C匯流排前,需要先配置ESP32 I2C控制器的傳輸環境參數配置,來配置ESP32 I2C以下參數: 1. ##### I2C工作模式 2. ##### 決定哪個GPIO作為SDA訊號線 3. ##### 決定哪個GPIO作為SCL時脈線 4. ##### SCL時脈頻率(最大4MHz) 5. ##### SDA和SCL GPIO需要啟用上拉電阻 6. ##### TX、RX Buffer ::: #### 把上述資料由Struct結構體數據結構儲存起來 ```c! int i2c_master_port = 0; i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, // 配置 SDA 的 GPIO .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_io_num = I2C_MASTER_SCL_IO, // 配置 SCL 的 GPIO .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = 400000, // 選擇時脈頻率 .clk_flags = 0, }; ``` #### 將上述i2c_config_t結構體作為參數,進行esp32 driver參數配置及初始化 ```c! i2c_param_config(i2c_master_port, &conf); ``` :::info Paramater * ##### i2c_master_port: ESP32 I2C控制器編號 * ##### conf: 上述程式之結構體,由I2C各參數所組成 ::: ### **2.安裝I2C驅動** ```c! i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0); ``` :::info #### **Paramater** ##### * i2c_master_port: ESP32提供2個I2C控制器,本例子使用第一個控制器,為 0 ##### * conf.mode: I2C工作模式,選擇工作於Master模式 ##### * I2C_MASTER_RX_BUF_DISABLEI2C_MASTER_TX_BUF_DISABLE無使用,則寫入0 ::: ## **ESP32 I2C Write data / Read Date from I2C-Bus** * ### **Write data** ![](https://hackmd.io/_uploads/Sk0zSin02.png) #### ESP32工作於Master模式,藉由下圖流程,進行n Bytes的資料寫入,寫入至slave address中的特定寄存器 :::info ##### 1.建立cmd為i2c通訊命令Link ##### 2.發起Start訊號 ##### 3.寫入8位元資料,其中7位元為slave位址,1位元選擇R/W,等待ACK回應 ##### 4.收到ACK後,發送Data,並等待ACK ##### 5.送出結束字元,STOP ##### 6.將上述設定好的流程,開始發送所有資料至I2C-Bus ##### 7.釋放資源,記憶體 ::: * ### **Read Data** ![](https://hackmd.io/_uploads/Hy-6rohRh.png) #### ESP32工作於Master模式,藉由下圖流程,進行n Bytes的資料讀取,讀取slave address中的特定寄存器內的資料 :::info ```c! i2c_master_write_byte(cmd, (ESP_SLAVE_ADDR << 1) | I2C_MASTER_WRITE, ACK_EN); ``` ```c! i2c_master_write_byte(cmd, (ESP_SLAVE_ADDR << 1) | I2C_MASTER_READ, ACK_EN); ``` I2C在Write和Read不同的點在於slave address為固定7bit的位址,我們需要在LSB最低位元選擇(0 OR 1),讓I2C-Bus來辨別這一連串的資料是要用於讀取slave寄存器資料還是用於寫入資料到slave寄存器中,所以要在LSB(最低位元),寫入I2C_MASTER_WRITE(0)或者I2C_MASTER_READ(1) ::: ## **ESP32 I2C Write data / Read Date from I2C-Bus API** #### 1. 由SENSOR_ADDR讀取n Bytes的資料 ```c! i2c_master_write_read_device(I2C_MASTER_NUM, SENSOR_ADDR, &reg_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); ``` #### 2. 向SENSOR_ADDR寫入1 Bytes的資料 ```c! i2c_master_write_to_device(I2C_MASTER_NUM, SENSOR_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); ``` --- #### 我們可以藉由I2C-Bus上寫入或讀取用來配置Slave寄存器的內容,也可以藉由讀取,來獲取Slave寄存器內的資料。 #### 下一章節,我們將使用I2C-Bus來使用Mpu6050六軸感測器。 --- * ### **Mpu6050六軸感測器實作教學影片** ![](https://hackmd.io/_uploads/B1afJDp03.png) * [https://www.youtube.com/watch?v=ZGw88J1PExE](https://www.youtube.com/watch?v=ZGw88J1PExE)