一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

ESP32學(xué)習(xí)筆記:I2C

CHANBAEK ? 來源:跳動(dòng)的字節(jié) ? 作者:曉宇 ? 2023-07-14 14:56 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

今天我們來玩兒I2C。

I2C概述

I2C全稱是Inter-Integrated Circuit,是飛利浦半導(dǎo)體公司(06年遷移到NXP了)在1982年發(fā)明的,是使用非常廣泛的一種通信協(xié)議,很多傳感器、存儲(chǔ)芯片、OLED等,都是在使用I2C。標(biāo)準(zhǔn)輸出模式下能達(dá)到100kbps的傳輸速率,快速模式下能達(dá)到400kbps的傳輸速率,高速模式下能達(dá)到3.4Mbps,超高速下最快能達(dá)到5Mbps。

UART一樣,IIC僅用兩條線在設(shè)備間通信:

圖片

SCL -- 時(shí)鐘信號(hào)

SDA-- 數(shù)據(jù)信號(hào)

I2C主機(jī)與從機(jī)之間共享時(shí)鐘信號(hào),時(shí)鐘始終由主機(jī)控制,總線下面可以掛多個(gè)設(shè)備,是一種同步,多主,多從,半雙工的通信協(xié)議,下面我們簡(jiǎn)單介紹一下通信原理:

圖片

默認(rèn)情況下,兩條線都被上拉,SCL=1,SDA=1。

啟動(dòng)與停止信號(hào):

通信開始,要先發(fā)開啟動(dòng)信號(hào),結(jié)束的時(shí)候,要發(fā)送結(jié)束信號(hào)。

開始信號(hào)由主設(shè)備發(fā)出啟動(dòng),具體為在SCL高電平期間,SDA從高電平切換到低電平;

停止信號(hào)由主設(shè)備發(fā)出結(jié)束,具體為在SCL高電平期間,SDA從低電平切換到高電平;

圖片

當(dāng)然,在傳輸過程中,有時(shí)候需要更改數(shù)據(jù)方向,重新傳輸?shù)?,我們沒必要發(fā)停止信號(hào),直接重新發(fā)啟動(dòng)信號(hào)啟動(dòng)即可。

圖片

地址字節(jié)

我們的總線上可能掛很多從設(shè)備,在我們主設(shè)備發(fā)送了啟動(dòng)信號(hào)之后,總線上的從設(shè)備就都被“喚醒”了,等著主設(shè)備發(fā)送地址寵幸。所以這里有一個(gè)從機(jī)地址的概念,從機(jī)地址以8位字節(jié)發(fā)送的,MSB在前,最后一位表示接下來讀或?qū)懀愿?位構(gòu)成了從機(jī)地址,也可以看出,同一個(gè)總線上,可以尋址128個(gè)從設(shè)備。

一旦從設(shè)備的地址匹配,就繼續(xù)讀取最后一位,低電平代表寫入,高電平代表讀取。其它從設(shè)備就忽略后面的數(shù)據(jù)。

ACK與NACK

在每個(gè)字節(jié)傳輸之后,接收設(shè)備發(fā)送一個(gè)應(yīng)答信號(hào),確認(rèn)或者不確認(rèn),接收設(shè)備通過在SCL高電平期間,將SDA拉低生成一個(gè)確認(rèn)信號(hào)ACK,拉高生成一個(gè)不確認(rèn)信號(hào)NACK,這里ACK主要用于表示字節(jié)正確傳輸了,NACK表示數(shù)據(jù)傳輸有錯(cuò)誤,需要從新發(fā)送。應(yīng)答信號(hào)主設(shè)備,從設(shè)備都可以產(chǎn)生,比如,主設(shè)備從從設(shè)備讀取最后一個(gè)字節(jié)的數(shù)據(jù)后,就要發(fā)送NACK結(jié)束傳輸。

圖片

數(shù)據(jù)信號(hào)

數(shù)據(jù)以8位字節(jié)格式傳輸,高字節(jié)在前,傳輸?shù)淖止?jié)數(shù)量沒有限制,但是每個(gè)字節(jié)后面必須要有一個(gè)數(shù)據(jù)接收方產(chǎn)生的應(yīng)答信號(hào)。傳輸過程中,SCL為低的時(shí)候,SDA數(shù)據(jù)可以改變,SCL為高的時(shí)候,SDA的數(shù)據(jù)必須穩(wěn)定。

圖片

命令字節(jié)

當(dāng)寫入或讀取從設(shè)備中特定寄存器時(shí),主機(jī)首先要向已尋址的從機(jī)寫入寄存器地址,其實(shí)也是一個(gè)數(shù)據(jù)字節(jié),我們這里稱之為命令字節(jié)。

寫入設(shè)備

主設(shè)備在發(fā)出啟動(dòng)信號(hào)之后,緊著著發(fā)送要操作從設(shè)備的地址,最后一位為低電平表示接下來寫入數(shù)據(jù),然后在時(shí)鐘信號(hào)下一位一位的寫入數(shù)據(jù),在從設(shè)備發(fā)出ACK應(yīng)答之后,發(fā)送結(jié)束信號(hào)結(jié)束通信。

圖片

讀取數(shù)據(jù)

主設(shè)備在發(fā)出啟動(dòng)信號(hào)之后,緊著著發(fā)送要操作從設(shè)備的地址,最后一位為高電平表示接下來讀取數(shù)據(jù),然后接管SDA數(shù)據(jù)線并在時(shí)鐘的控制下向主設(shè)備發(fā)送數(shù)據(jù),主設(shè)備同樣要在每個(gè)字節(jié)接收完畢的時(shí)候發(fā)送ACK響應(yīng),當(dāng)主設(shè)備不想接收的時(shí)候,就在最后一個(gè)字節(jié)接收后發(fā)送NACK響應(yīng),然后恢復(fù)對(duì)總線的控制并發(fā)送結(jié)束信號(hào)。

SCL的控制權(quán)始終在主機(jī)這里。

圖片

當(dāng)然,實(shí)際還要很多組合傳輸協(xié)議,這里由于篇幅問題就不展開說了,基本上大同小異,我們根據(jù)不同設(shè)備的數(shù)據(jù)手冊(cè)來傳輸就可以啦。I2C還有很多特性,快速命令,仲裁,多主控等等,普通的應(yīng)用接觸不到,感興趣的小伙伴自行研究下。

硬件

ESP32有2個(gè)硬件I2C總線接口,接口可以配置為主機(jī)或從機(jī)模式,支持如下特性:

  • 標(biāo)準(zhǔn)模式 (100 Kbit/s)
  • 快速模式 (400 Kbit/s)
  • 高達(dá) 5 MHz,但受 SDA 上拉強(qiáng)度的限制
  • 7位/10位尋址模式
  • 雙尋址模式,用戶可以通過編程命令寄存器來控制 I2C 接口,讓他們有更大的靈活性

SDA與SCL是低電平有效的,所以我們應(yīng)該在兩根數(shù)據(jù)線上用電阻上拉,IO內(nèi)部也是開漏輸出的,一般5V系統(tǒng)接4.7K上拉,3.3V系統(tǒng)接2.4K上拉即可。ESP32上,SDA默認(rèn)連接GPIO21,SCL默認(rèn)連接GPIO22,當(dāng)然,我們可以在代碼中配置到任何引腳。

圖片

軟件

啟動(dòng)I2C

啟動(dòng)Wire庫(kù)并作為主機(jī)或者從機(jī)加入總線,這個(gè)函數(shù)調(diào)用一次即可,參數(shù)為7位從機(jī)地址,不帶參數(shù)就以主機(jī)的形式加入總線。

Wire.begin();
Wire.begin(address)

主設(shè)備從從設(shè)備請(qǐng)求字節(jié)

由主設(shè)備向從設(shè)備請(qǐng)求字節(jié),之后用available()和read()函數(shù)讀取字節(jié),第三個(gè)參數(shù)位為stop,在請(qǐng)求后會(huì)發(fā)送停止消息,釋放I2C總線,否則總線就不會(huì)被釋放。

Wire.requestFrom(address, quantity);
Wire.requestFrom(address, quantity, stop);

給指定地址的從設(shè)備傳輸數(shù)據(jù)

給指定地址的從設(shè)備傳輸數(shù)據(jù),之后調(diào)用write()函數(shù)排隊(duì)傳輸字節(jié),要通過endTransmission()結(jié)束傳輸。

Wire.beginTransmission(address)

endTransmission()有以下幾個(gè)返回結(jié)果:

  • 0:成功
  • 1:數(shù)據(jù)太長(zhǎng),無法放入發(fā)送緩沖區(qū)
  • 2:在發(fā)送地址時(shí)收到 NACK
  • 3:在發(fā)送數(shù)據(jù)時(shí)收到 NACK
  • 4:其他錯(cuò)誤

寫數(shù)據(jù)

向從設(shè)備寫入數(shù)據(jù),在調(diào)用 beginTransmission() 和 endTransmission() 之間。

Wire.write(value)
Wire.write(string)
Wire.write(data, length)

舉個(gè)例子

#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);
}

讀數(shù)據(jù)

調(diào)用requestFrom()后從從設(shè)備讀取數(shù)據(jù)。

Wire.read()

舉個(gè)例子

#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);
}

還有其它一些函數(shù),例如修改時(shí)鐘頻率等等,大家用到的時(shí)候自行了解一下。

完整程序

這里我們用一個(gè)例子來演示一下,I2C啟動(dòng)之后,我們開始掃描總線上存在的設(shè)備,并通過串口打印結(jié)果出來,我在I2C下面接了一個(gè)OLED的設(shè)備。

#include "Wire.h"

void setup(){
  Serial.begin(115200); 
  Serial.println();
  Serial.println("Scanning for I2C Devices ...");
  Serial.print("rn");
  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("沒有發(fā)現(xiàn)I2C設(shè)備!n");
  }
  else
  {   
    Serial.print("發(fā)現(xiàn)了");
    Serial.print(I2CDevices);
    Serial.println("個(gè)I2C設(shè)備!n");  
  }  
}

void loop(){
}

Wire.endTransmission()返回0,代表這個(gè)地址通信成功,我們就認(rèn)為總線上存在這個(gè)地址的設(shè)備。

圖片

I2C OLED

I2C只是個(gè)通信協(xié)議,具體的還是要結(jié)合實(shí)物來演示,比如一些傳感器或者屏幕,這里我們用I2C協(xié)議的0.96寸OLED屏幕來演示下:

圖片

OLED使用SSD1306控制芯片,所以我們需要下載一個(gè)庫(kù)SSD1306,另外還需要配合圖形庫(kù)GFX操作,代碼中,我們先包含對(duì)應(yīng)頭文件,然后創(chuàng)建一個(gè)Adafruit_SSD1306對(duì)象,第三個(gè)參數(shù)是用的I2C對(duì)象。

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

初始化時(shí)候用display.begin(SSD1306_SWITCHCAPVCC, 0x3C)初始化顯示對(duì)象,傳入地址,然后就可以自由簡(jiǎn)單的顯示我們想要顯示的數(shù)據(jù)了。

關(guān)于Adafruit_GFX庫(kù),非常強(qiáng)大的一個(gè)圖形庫(kù),我們后面單獨(dú)講解具體的原理,這里先了解一下即可。

完整程序

#include < Wire.h >
#include < Adafruit_GFX.h >
#include < Adafruit_SSD1306.h >

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(115200);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }  
  delay(1000);
  display.display();
  
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0,0);
  display.print("CHIPHOME");
  display.display();
  display.setCursor(0,8);
  display.print("12345678");
  display.display();
  delay(1000);
}
void loop() {

}

SSD1306示例代碼演示:

圖片

感謝大家,關(guān)于ESP32的學(xué)習(xí),希望大家Enjoy!

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 傳感器
    +關(guān)注

    關(guān)注

    2565

    文章

    52974

    瀏覽量

    767213
  • 通信協(xié)議
    +關(guān)注

    關(guān)注

    28

    文章

    1033

    瀏覽量

    41155
  • 總線
    +關(guān)注

    關(guān)注

    10

    文章

    2959

    瀏覽量

    89731
  • I2C
    I2C
    +關(guān)注

    關(guān)注

    28

    文章

    1541

    瀏覽量

    127791
  • ESP32
    +關(guān)注

    關(guān)注

    21

    文章

    1017

    瀏覽量

    19245
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    I2C總線學(xué)習(xí)筆記

    I2C在小P以前接觸的設(shè)計(jì)中大多只用到400k的速率,EVB的設(shè)計(jì)中更經(jīng)常發(fā)現(xiàn)實(shí)現(xiàn)不了就降速到100k?,F(xiàn)在突然再看看I2C,發(fā)現(xiàn)原來還有更高的速率規(guī)范,最高都已經(jīng)到5M了。
    的頭像 發(fā)表于 10-25 14:35 ?2696次閱讀
    <b class='flag-5'>I2C</b>總線<b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>

    ESP32ESP-IDF學(xué)習(xí)筆記

    ESP32ESP-IDF 學(xué)習(xí)筆記(六)【I2C數(shù)據(jù)總線(I2
    發(fā)表于 02-22 07:30

    基于51的I2c總線

    I2c總線,基于51的I2c總線,程序學(xué)習(xí)??靵硐螺d學(xué)習(xí)
    發(fā)表于 01-13 11:49 ?34次下載

    STM32學(xué)習(xí)I2C協(xié)議(讀寫EEPROM)

    關(guān)于STM32學(xué)習(xí)分享第七章 I2C協(xié)議(讀寫EEPROM)文章目錄關(guān)于STM32學(xué)習(xí)分享前言二、代碼1.i2c.c2.i2c.h3.main.c總結(jié)前言開始!開始!單片機(jī)的
    發(fā)表于 11-30 15:21 ?32次下載
    STM32<b class='flag-5'>學(xué)習(xí)</b>之<b class='flag-5'>I2C</b>協(xié)議(讀寫EEPROM)

    [ESP32]學(xué)習(xí)筆記02

    [ESP32學(xué)習(xí)筆記02]使用ViusalStudio2017開發(fā)ESP32、按鍵輸入檢測(cè)前言一、安裝Visual Studio 2017二、配置開發(fā)環(huán)境1.安裝ViusalGDB
    發(fā)表于 12-03 17:36 ?23次下載
    [<b class='flag-5'>ESP32</b>]<b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>02

    ESP32 單片機(jī)學(xué)習(xí)筆記 - 02 - 軟件IIC&硬件SPI

    :esp-idf/examples/peripherals/i2c/i2c_self_test/,官方給的硬件iic例程,我之前用慣的都是軟件iic。官方指南:I2C 驅(qū)動(dòng)程序,開篇第
    發(fā)表于 12-04 15:21 ?7次下載
    <b class='flag-5'>ESP32</b> 單片機(jī)<b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b> - 02 - 軟件IIC&硬件SPI

    I2C和SPI學(xué)習(xí)筆記

    I2C通信協(xié)議I2C通信原理I2C通信原理:I2C是一種半雙工通信方式,主要時(shí)鐘線SCL和數(shù)據(jù)線SDA構(gòu)成,速率一般為400Mbps總線信號(hào)有三種:開始信號(hào);結(jié)束信號(hào);應(yīng)答信號(hào)當(dāng)時(shí)鐘線
    發(fā)表于 12-22 19:20 ?1次下載
    <b class='flag-5'>I2C</b>和SPI<b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>

    SPI主線協(xié)議——ESP32學(xué)習(xí)筆記

    目錄SPI主線協(xié)議——ESP32學(xué)習(xí)筆記零、前言一、什么是SPI?二、通信過程?三、極性和相位四、總結(jié)SPI主線協(xié)議——ESP32學(xué)習(xí)
    發(fā)表于 12-22 19:23 ?18次下載
    SPI主線協(xié)議——<b class='flag-5'>ESP32</b><b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>筆記</b>

    ESP32ESP-IDF 教學(xué)(六)——I2C數(shù)據(jù)總線(I2C

    ESP32ESP-IDF 學(xué)習(xí)筆記(六)【I2C數(shù)據(jù)總線(I2
    發(fā)表于 12-28 19:25 ?22次下載
    <b class='flag-5'>ESP32</b> 之 <b class='flag-5'>ESP</b>-IDF 教學(xué)(六)——<b class='flag-5'>I2C</b>數(shù)據(jù)總線(<b class='flag-5'>I</b>2<b class='flag-5'>C</b>)

    ESP32-C2ESP32-C3有哪些不同

    ESP32-C2 集成 2.4 GHz Wi--Fi 和支持長(zhǎng)距離的 Bluetooth 5 (LE),搭載 RISC-V 32位單核處理器,時(shí)鐘頻率高達(dá) 120 MHz,內(nèi)置 272 KB
    發(fā)表于 12-29 18:11 ?1.1w次閱讀
    <b class='flag-5'>ESP32-C2</b>與<b class='flag-5'>ESP32-C</b>3有哪些不同

    ESP 12E I2c基卡的I2C IO卡設(shè)計(jì)

    電子發(fā)燒友網(wǎng)站提供《ESP 12E I2c基卡的I2C IO卡設(shè)計(jì).zip》資料免費(fèi)下載
    發(fā)表于 08-15 09:27 ?3次下載
    <b class='flag-5'>ESP</b> 12E <b class='flag-5'>I2c</b>基卡的<b class='flag-5'>I2C</b> IO卡設(shè)計(jì)

    ESP32 S2 WROVER/ESP32 S2 WROVER I技術(shù)規(guī)格書

    電子發(fā)燒友網(wǎng)站提供《ESP32 S2 WROVER/ESP32 S2 WROVER I技術(shù)規(guī)格書.pdf》資料免費(fèi)下載
    發(fā)表于 09-23 11:48 ?2次下載
    <b class='flag-5'>ESP32</b> S<b class='flag-5'>2</b> WROVER/<b class='flag-5'>ESP32</b> S<b class='flag-5'>2</b> WROVER <b class='flag-5'>I</b>技術(shù)規(guī)格書

    ESP32 S2 WROOM/ESP32 S2 WROOM I技術(shù)規(guī)格書

    電子發(fā)燒友網(wǎng)站提供《ESP32 S2 WROOM/ESP32 S2 WROOM I技術(shù)規(guī)格書.pdf》資料免費(fèi)下載
    發(fā)表于 09-23 11:31 ?4次下載
    <b class='flag-5'>ESP32</b> S<b class='flag-5'>2</b> WROOM/<b class='flag-5'>ESP32</b> S<b class='flag-5'>2</b> WROOM <b class='flag-5'>I</b>技術(shù)規(guī)格書

    用于ESP 12E I2C基卡的I2C IO卡

    電子發(fā)燒友網(wǎng)站提供《用于ESP 12E I2C基卡的I2C IO卡.zip》資料免費(fèi)下載
    發(fā)表于 06-09 09:47 ?0次下載
    用于<b class='flag-5'>ESP</b> 12E <b class='flag-5'>I2C</b>基卡的<b class='flag-5'>I2C</b> IO卡

    GitHub Copilot+ESP開發(fā)實(shí)戰(zhàn)-I2C

    準(zhǔn)備工作1.ESP32-S3-DevKitC-1開發(fā)板一塊;2.LM75A溫度感應(yīng)器;3.杜邦線4根、USB線;一、向Copilot提問1.ESP32-S3用C語言實(shí)現(xiàn)
    的頭像 發(fā)表于 03-29 08:03 ?805次閱讀
    GitHub Copilot+<b class='flag-5'>ESP</b>開發(fā)實(shí)戰(zhàn)-<b class='flag-5'>I2C</b>