您的位置 首页 > 数码极客

esp32如何让oled屏幕亮起来

ESP32具有两个I2C总线接口,可用作I2C主站或从站。在本教程中,我们将使用Arduino IDE查看与ESP32的I2C通信协议:如何选择I2C引脚,将多个I2C设备连接到同一总线以及如何使用两个I2C总线接口。

在本教程中,我们将介绍以下概念:

  • 将I2C设备与ESP32连接
  • 使用ESP32扫描I2C地址
  • ESP32使用不同的I2C引脚(更改默认I2C引脚)
  • ESP32使用两个I2C总线接口
  • 我们将使用Arduino IDE对ESP32进行编程,因此在继续本教程之前,您应该在Arduino IDE中安装ESP32插件。
  • 具有多个I2C器件的ESP32
  • 1. 相同的总线,不同的地址

    2. 相同的地址·

    ESP32 I2C通讯协议介绍

    I²C是一个同步,多主,多从通信协议。您可以连接:

  • 一个主设备有多个从设备:例如,您的ESP32使用I2C从BME280传感器读取数据,并将传感器读数写入I2C OLED显示屏。
  • 多个主设备控制同一个从设备:例如,两个ESP32板将数据写入同一I2C OLED显示器。
  • 我们在ESP32中多次使用此协议与外部设备(例如传感器和显示器)进行通信。在这种情况下,ESP32是主芯片,外部设备是从芯片。

    ESP32 I2C总线接口

    ESP32通过其两个I2C总线接口支持I2C通信,这两个接口可以用作I2C主设备或从设备,具体取决于用户的配置。根据ESP32数据表,ESP32的I2C接口支持:

  • 标准模式(100 Kbit / s)
  • 快速模式(400 Kbit / s)
  • 高达5 MHz,但受到SDA上拉强度的限制
  • 7位/ 10位寻址模式
  • 双寻址模式。用户可以对命令寄存器进行编程以控制I²C接口,从而具有更大的灵活性
  • 将I2C设备与ESP32连接

    I2C通信协议使用两条线共享信息。一个用于时钟信号(SCL),另一个用于发送和接收数据(SDA)。

    注意:在许多分支板上,SDA线也可能标记为SDI,SCL线也可能标记为SCK。

    SDA和SCL线为低电平有效,因此应使用电阻将其上拉。对于5V器件,典型值为4.7k Ohm;对于3.3V器件,典型值为2.4k Ohm。

    我们在项目中使用的大多数传感器都是已内置电阻的分线板。因此,通常,当您处理此类电子元件时,您无需为此担心。

    将I2C器件连接到ESP32通常很简单,只需将GND连接到GND,将SDA连接到SDA,将SCL连接到SCL并将正电源连接到外围设备通常为3.3V(但这取决于您使用的模块)。

    将ESP32与Arduino IDE结合使用时,默认的I2C引脚为GPIO 22(SCL)和GPIO 21(SDA),但您可以将代码配置为使用任何其他引脚。


    通过I2C通信,总线上的每个从站都有其自己的地址,此十六进制数允许ESP32与每个设备通信。

    I2C地址通常可以在组件的数据表中找到。但是,如果很难查明,则可能需要运行I2C查找程序以查明I2C地址。

    您可以使用以下程序找到设备的I2C地址。

    #include <Wire.h>

    void setup() {

    Wire.begin();

    Serial.begin(115200);

    Serial.println("\nI2C Scanner");

    }

    void loop() {

    byte error, address;

    int nDevices;

    Serial.println("Scanning...");

    nDevices = 0;

    for(address = 1; address < 127; address++ ) {

    Wire.beginTransmission(address);

    error = Wire.endTransmission();

    if (error == 0) {

    Serial.print("I2C device found at address 0x");

    if (address<16) {

    Serial.print("0");

    }

    Serial.println(address,HEX);

    nDevices++;

    }

    else if (error==4) {

    Serial.print("Unknow error at address 0x");

    if (address<16) {

    Serial.print("0");

    }

    Serial.println(address,HEX);

    }

    }

    if (nDevices == 0) {

    Serial.println("No I2C devices found\n");

    }

    else {

    Serial.println("done\n");

    }

    delay(5000);

    }

    您会在串口监视器中看到类似的内容。此特定示例适用于。

    ESP32使用不同的I2C引脚(更改默认I2C引脚)

    使用ESP32,您几乎可以将任何引脚设置为具有I2C功能,您只需要在代码中进行设置即可。

    将ESP32与Arduino IDE配合使用时,请使用Wire.h库与使用I2C的设备进行通信。使用此库,您可以按以下方式初始化I2C:

    Wire.begin(I2C_SDA, I2C_SCL);

    因此,您只需要在I2C_SDA和I2C_SCL变量上设置所需的SDA和SCL GPIO 。

    但是,如果您使用库与这些传感器进行通信,则这可能无法正常工作,选择其他引脚可能会有些棘手。发生这种情况是因为,如果在初始化库时不传递自己的Wire实例,这些库可能会覆盖您的引脚。

    在这种情况下,您需要仔细查看.cpp库文件,并了解如何传递自己的TwoWire参数。

    例如,如果您仔细看一下,您会发现可以将自己的TwoWire传递给begin()方法。

    因此,使用其他引脚(例如,GPIO 33作为SDA和GPIO 32作为SCL)从BME280读取示例程序如下。

    #include <Wire.h>

    #include <Ada;

    #include <Ada;

    #define I2C_SDA 33

    #define I2C_SCL 32

    #define SEALEVELPRESSURE_HPA )

    TwoWire I2CBME = TwoWire(0);

    Adafruit_BME280 bme;

    unsigned long delayTime;

    void setup() {

    Serial.begin(115200);

    Serial.println(F("BME280 test"));

    I2CBME.begin(I2C_SDA, I2C_SCL, 100000);

    bool status;

    status = bme.begin(0x76, &I2CBME);

    if (!status) {

    Serial.println("Could not find a valid BME280 sensor, check wiring!");

    while (1);

    }

    Serial.println("-- Default Test --");

    delayTime = 1000;

    Serial.println();

    }

    void loop() {

    printValues();

    delay(delayTime);

    }

    void printValues() {

    Serial.print("Temperature = ");

    Serial.prin());

    Serial.println(" *C");

    Serial.print("Pressure = ");

    Serial.prin() / 100.0F);

    Serial.println(" hPa");

    Serial.print("Approx. Altitude = ");

    Serial.prin(SEALEVELPRESSURE_HPA));

    Serial.println(" m");

    Serial.print("Humidity = ");

    Serial.prin());

    Serial.println(" %");

    Serial.println();

    }


    让我们看一下使用其他I2C引脚的相关部分。

    首先,在I2C_SDA和I2C_SCL变量上定义新的I2C引脚。在这种情况下,我们使用的是GPIO 33和GPIO 32。

    #define I2C_SDA 33

    #define I2C_SCL 32

    创建一个新的TwoWire实例。在这种情况下,它称为I2CBME。这只是创建一个I2C总线。

    TwoWire I2CBME = TwoWire(0);

    在setup()中,使用您先前定义的引脚初始化I2C通信。第三个参数是时钟频率。

    I2CBME.begin(I2C_SDA, I2C_SCL, 400000);

    最后,用您的传感器地址和TwoWire对象初始化一个BME280对象。

    status = bme.begin(0x76, &I2CBME);

    之后,您可以对bme对象使用常规方法来请求温度,湿度和压力。

    注意:如果您使用的库在其文件中使用诸如wire.begin()之类的语句,则可能需要注释该行,以便可以使用自己的引脚。

    具有多个I2C器件的ESP32

    如前所述,每个I2C设备都有其自己的地址,因此可能在同一总线上具有多个I2C设备。

    多个I2C设备(相同的总线,不同的地址)

    当我们有多个具有不同地址的设备时,如何设置它们很简单:

  • 将两个外设都连接到ESP32的SCL和SDA线路;
  • 在代码中,通过其地址引用每个外围设备;
  • 看下面的示例,该示例从BME280传感器(通过I2C)获取传感器读数,并将结果显示在I2C OLED显示器上。

    #include <Wire.h>

    #include <Ada;

    #include <Ada;

    #include <Ada;

    #include <Ada;

    #define SCREEN_WIDTH 128

    #define SCREEN_HEIGHT 64

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

    Adafruit_BME280 bme;

    void setup() {

    Serial.begin(115200);

    if(!di(SSD1306_SWITCHCAPVCC, 0x3C)) {

    Serial.println(F("SSD1306 allocation failed"));

    for(;;);

    }

    bool status = bme.begin(0x76);

    if (!status) {

    Serial.println("Could not find a valid BME280 sensor, check wiring!");

    while (1);

    }

    delay(2000);

    di();

    di(WHITE);

    }

    void loop() {

    di();

    di(1);

    di(0,0);

    di("Temperature: ");

    di(2);

    di(0,10);

    di(String()));

    di(" ");

    di(1);

    di(true);

    di(167);

    di(2);

    di("C");

    di(1);

    di(0, 35);

    di("Humidity: ");

    di(2);

    di(0, 45);

    di(String()));

    di(" %");

    di();

    delay(1000);

    }


    由于OLED和BME280具有不同的地址,因此我们可以使用相同的SDA和SCL线,而不会出现任何问题。OLED显示地址为0x3C,BME280地址为0x76。

    if(!di(SSD1306_SWITCHCAPVCC, 0x3C)) {

    Serial.println(F("SSD1306 allocation failed"));

    for(;;);

    }

    bool status = bme.begin(0x76);

    if (!status) {

    Serial.println("Could not find a valid BME280 sensor, check wiring!");

    while (1);

    }

    多个I2C设备(相同地址)

    但是,如果您有多个具有相同地址的外设怎么办?例如,多个OLED显示器或多个BME280传感器?有几种解决方案。

  • 更改设备的I2C地址;
  • 使用I2C多路复用器。
  • 更改I2C地址

    许多分线板都可以选择根据其电路更改I2C地址。例如,看下面的OLED显示器。


    通过将电阻器放在一侧或另一侧,可以选择不同的I2C地址。其他组件也会发生这种情况。

    使用I2C多路复用器

    但是,在前面的示例中,这仅允许您在同一总线上具有两个I2C显示器:一个具有0x3C地址,另一个具有0x3D地址。

    此外,有时更改I2C地址并非易事。因此,为了在同一I2C总线中拥有多个具有相同地址的设备,您可以使用I2C多路复用器,如TCA9548A,它允许您与多达8个具有相同地址的设备进行通信。

    ESP32使用两个I2C总线接口

    要使用ESP32的两个I2C总线接口,您需要创建两个TwoWire实例。

    TwoWire I2Cone = TwoWire(0);

    TwoWire I2Ctwo = TwoWire(1)

    然后,以所需的频率在所需的引脚上初始化I2C通信。

    void setup() {

    I2Cone.begin(SDA_1, SCL_1, freq1);

    I2C(SDA_2, SCL_2, freq2);

    }


    然后,您可以使用Wire.h库中的方法与I2C总线接口进行交互。

    一个更简单的替代方法是使用预定义的Wire()和Wire1()对象。Wire()。begin()使用默认引脚和默认频率在第一条I2C总线上创建I2C通信。对于Wire1.begin(),您应该传递所需的SDA和SCL引脚以及频率。

    setup(){

    Wire.begin();

    Wire1.begin(SDA_2, SCL_2, freq);

    }

    这种方法允许您使用两条I2C总线,其中一条使用默认参数。

    为了更好地了解其工作原理,我们来看一个简单的示例,该示例从两个BME280传感器读取温度,湿度和压力。

    每个传感器都连接到不同的I2C总线。

    · I2C总线1:使用GPIO 27(SDA)和GPIO 26(SCL);

    · I2C总线2:使用GPIO 33(SDA)和GPIO 32(SCL);

    #include <Wire.h>

    #include <Ada;

    #include <Ada;

    #define SDA_1 27

    #define SCL_1 26

    #define SDA_2 33

    #define SCL_2 32

    TwoWire I2Cone = TwoWire(0);

    TwoWire I2Ctwo = TwoWire(1);

    Adafruit_BME280 bme1;

    Adafruit_BME280 bme2;

    void setup() {

    Serial.begin(115200);

    Serial.println(F("BME280 test"));

    I2Cone.begin(SDA_1, SCL_1, 100000);

    I2C(SDA_2, SCL_2, 100000);

    bool status1 = bme1.begin(0x76, &I2Cone);

    if (!status1) {

    Serial.println("Could not find a valid BME280_1 sensor, check wiring!");

    while (1);

    }

    bool status2 = bme2.begin(0x76, &I2Ctwo);

    if (!status2) {

    Serial.println("Could not find a valid BME280_2 sensor, check wiring!");

    while (1);

    }

    Serial.println();

    }

    void loop() {

    Serial.print("Temperature from BME1= ");

    Serial.prin());

    Serial.println(" *C");

    Serial.print("Humidity from BME1 = ");

    Serial.prin());

    Serial.println(" %");

    Serial.print("Pressure from BME1 = ");

    Serial.prin() / 100.0F);

    Serial.println(" hPa");

    Serial.println("--------------------");

    Serial.print("Temperature from BME2 = ");

    Serial.prin());

    Serial.println(" *C");

    Serial.print("Humidity from BME2 = ");

    Serial.prin());

    Serial.println(" %");

    Serial.print("Pressure from BME2 = ");

    Serial.prin() / 100.0F);

    Serial.println(" hPa");

    Serial.println("--------------------");

    delay(5000);

    }

    让我们看一下使用两个I2C总线接口的相关部分。

    定义要使用的SDA和SCL引脚:

    #define SDA_1 27

    #define SCL_1 26

    #define SDA_2 33

    #define SCL_2 32

    创建两个TwoWire对象(两个I2C总线接口):

    TwoWire I2Cone = TwoWire(0);

    TwoWire I2Ctwo = TwoWire(1);

    创建Adafruit_BME280库的两个实例以与您的传感器进行交互:bme1和bme2。

    Adafruit_BME280 bme1;

    Adafruit_BME280 bme2;

    在定义的引脚和频率上初始化I2C通信:

    I2Cone.begin(SDA_1, SCL_1, 100000);

    I2C(SDA_2, SCL_2, 100000);

    然后,应使用正确的地址和I2C总线初始化bme1和bme2对象。bme1使用I2Cone:

    bool status = bme1.begin(0x76, &I2Cone);

    而bme2用途I2Ctwo:

    bool status1 = bme2.begin(0x76, &I2Ctwo);

    现在,您可以在bme1和bme2对象上使用Adafruit_BME280库中的方法来读取温度,湿度和压力。

    另一种选择

    为了简单起见,可以使用预定义的Wire()和Wire1()对象:

    · Wire():在默认引脚GPIO 21(SDA)和GPIO 22(SCL)上创建I2C总线

    · Wire1(SDA_2,SCL_2,freq):以所需的频率在定义的SDA_2和SCL_2引脚上创建I2C总线。


    这是相同的示例,但是使用此方法。现在,您的一个传感器使用默认引脚,另一个传感器使用GPIO 32和GPIO 33。

    #include <Wire.h>

    #include <Ada;

    #include <Ada;

    #define SDA_2 33

    #define SCL_2 32

    Adafruit_BME280 bme1;

    Adafruit_BME280 bme2;

    void setup() {

    Serial.begin(115200);

    Serial.println(F("BME280 test"));

    Wire.begin();

    Wire1.begin(SDA_2, SCL_2);

    bool status1 = bme1.begin(0x76);

    if (!status1) {

    Serial.println("Could not find a valid BME280_1 sensor, check wiring!");

    while (1);

    }

    bool status2 = bme2.begin(0x76, &Wire1);

    if (!status2) {

    Serial.println("Could not find a valid BME280_2 sensor, check wiring!");

    while (1);

    }

    Serial.println();

    }

    void loop() {

    Serial.print("Temperature from BME1= ");

    Serial.prin());

    Serial.println(" *C");

    Serial.print("Humidity from BME1 = ");

    Serial.prin());

    Serial.println(" %");

    Serial.print("Pressure from BME1 = ");

    Serial.prin() / 100.0F);

    Serial.println(" hPa");

    Serial.println("--------------------")

    Serial.print("Temperature from BME2 = ");

    Serial.prin());

    Serial.println(" *C");

    Serial.print("Humidity from BME2 = ");

    Serial.prin());

    Serial.println(" %");

    Serial.print("Pressure from BME2 = ");

    Serial.prin() / 100.0F);

    Serial.println(" hPa");

    Serial.println("--------------------");

    delay(5000);

    }

    您应该在串口监视器上同时获得两个传感器的读数。

    在本教程中,您了解了有关ESP32的I2C通信协议的更多信息。希望对您有帮助。

    责任编辑: 鲁达

    1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
    2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
    3.本站属于非营利性站点无毒无广告,请读者放心使用!

    “esp32如何让oled屏幕亮起来,ESP32接OLED屏幕,ESP32,OLED屏幕闪烁”边界阅读