esp32 在arduino1.8下的I2C引脚

本文记录了作者在使用ESP32进行I2C传感器连接时遇到的问题及解决过程,详细描述了如何确定默认的I2C引脚SDA和SCL,并通过查找多个层级的头文件最终定位到正确的引脚。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写的很叙事

 

在写下这篇日志的时候,我的心情是复杂的,有如释重负,有恐惧,有对乐鑫的esp32技术文档的撰写人亲切的问候。
如释重负:终于知道为什么esp的IO21和IO22引脚是SDA和SCL的默认接口。
恐惧:恐惧是给C++的,我这几天正好在网上看到别人说,C++语法可以特别特别恶心,常量特别特别难定位。我就在想有多难,有多恶心,CTRL+f很快就定位到了。然后这几天头头在捣鼓传感器,我就在旁边看着,学习学习。记下了当时他接的引脚号,回去自己捣鼓捣鼓,一般来说,接传感器都是要在程序里指定引脚的,我看了看样例代码里也没有指定就很纳闷(我也在头文件里面找,也没找到)。就问头头,为什么=这个不指定引脚啊?头头很随意的说“因为这个是使用I2C的接口,只需要指定传感器的编号(相当于人的手机号,每类传感器都有一个,也可以人为设定),esp32会自动扫描在总线上的设备,不用管接哪个引脚。”那我听了这话,就很感慨,原来现在传感器也这么智能了,就试了试其他的引脚,不行,我大概尝试了几十种组合方式,除了头头的那一种其他的都不行。这个时候也不好意思去问头头 ,感觉很简单的一个东西。于是就上网看看I2C协议,再看看一些实例,哦,原来随便接是说在同一个I2C接口上可以随便接很多个传感器,在这个I2C接口上会自动的扫描不同的传感器设备。好,那我们来看看esp32上的I2C接口是哪个引脚。如果不出所料应该是头头用的IO21,22
图片
emmmmmmmm,我的SDA和SCL呢?可能是这张图不够详细,我们看看官方给的引脚说明

图片
???还是没有,我们去群里找乐鑫的产品经理吧!他应该知道

图片
这...他说的是在idf环境下使用I2C如何定义引脚,我是在arduino1.8的环境下。问到这的时候,我突然害羞了,也就没和他说我和他讨论的不是一个环境下的。我就在想,这个引脚既然能被用作SDA和SCL,那么他肯定在某个头文件里指定了,就算是默认的那也一定要指定,不然怎么能用呢?然后我就从我用的样例代码的头文件里找,大概翻了有5层(重点:层),没找到,根本没有指定特定的引脚充当I2C接口。我突然突发奇想,找了找其他的样例代码,看看那些指定了I2C引脚的代码是怎么调用底层库去使用的。对比了一下应该是通过这句Wire.begin(14,15);但是为什么这个要指定引脚,而另一个Wire.begin();不指定也可以使用呢?我觉得有必要看看begin()究竟是个什么玩意。图片
这个就是Wire这个实体的类(请允许我用面向对象的思想这样称呼它),这里是给它默认值,我们可以看到sda和scl给赋了-1

图片
这里的begin()方法里面是指定参数的,那为什么Wire.begin();能直接用呢?我也没学过c++,但是不妨碍我大开脑洞,直接这样用而不带参数,应该使用的是上上张图中的默认值就是-1,-1。按照这个思路下去,相当于是Wire。begin(-1,-1);,再看看上图,如果我的参数都是-1,那么我的sda和scl引脚就赋值SDA和SCL,然后我就得去找这个SDA和SCL是什么?这时候我就很激动的按下了CTRL+f。
emmmmmmmmmmm,找不到,不在Wire.h和Wire.cpp的里,那只能说在他的下层了,也就是它们包含的头文件里,然后我就开始颤抖了,这一层套一层的,得翻到死啊!
你们一定猜不到我是怎么找到定义SDA的头文件的。
我在一层一层往上找头文件的时候,搜到一个Arduino.h的文件的时候,突然看见了这个
图片
pins_arduino.h,这个文件从名字上看,pin引脚,然后我就情不自禁地点了进去
图片 
很明显,这里就是在arduino1.8环境下esp32开发板的引脚定义文件,之前看到很多不同文件夹下的pins_arduino.h是各个不同类型板子的引脚定义文件,比如我的就是devkitc v4.
我觉得我这次找到这个算是非常幸运的,又一次感觉生活像段子,自己又活成了段子。
最后给予开发者文档的撰写者最为亲切的问候:你狠,这些东西你都不写清楚,文档上就tm写,啊!我们有2个I2C接口,你倒是指出默认的啊!一天天的,飘了你。

<think>好的,我现在需要帮助用户了解ESP32Arduino之间通过I2C进行通信的方法,并提供教程和示例代码。首先,我应该回忆一下I2C的基本知识。I2C是一种串行通信协议,使用两条线:SDA(数据线)和SCL(时钟线)。主设备控制通信,从设备响应主设备的指令。ESP32可以作为主设备或从设备,而Arduino通常在这里可能是指另一个微控制器,比如Arduino Uno,同样支持I2C。 接下来,用户提到的参考引用里提到了硬件连接,比如ESP32开发板和I2C传感器,但用户的问题是关于ESP32Arduino之间的通信。可能需要明确这里的“Arduino”是指另一个使用Arduino框架的设备,比如另一个ESP32或者Arduino Uno。假设用户是想让ESP32作为主设备,与另一个Arduino设备(作为从设备)通信,或者反过来。需要确认这一点,但用户的问题可能更偏向于ESP32使用Arduino IDE进行I2C通信,可能涉及连接传感器或其他I2C设备。 首先,硬件连接部分。ESP32I2C引脚通常可以是多个,但默认情况下,Arduino核心库可能使用特定的引脚,比如GPIO 21(SDA)和GPIO 22(SCL)。但不同的开发板可能有所不同,需要用户查阅自己的板子引脚图。例如,有些ESP32开发板的默认I2C引脚可能不同,或者用户可以自定义其他引脚作为SDA和SCL。 然后,编写代码部分。在Arduino IDE中,使用Wire库来进行I2C通信。对于ESP32作为主设备读取从设备的数据,比如传感器,代码结构通常包括初始化Wire库,开始传输,发送请求,读取数据,结束传输等步骤。例如,读取温湿度传感器的数据,可能需要发送特定的命令,然后读取返回的字节。 用户提供的引用中提到了具体的传感器型号,如DHT12、HTU21D等,这些传感器可能有自己的协议和数据格式,但I2C通信的基本步骤是通用的。可能需要指导用户如何扫描I2C地址,确定传感器的地址,然后根据传感器的手册编写读取数据的代码。 示例代码方面,可能需要分两部分:作为主设备读取从设备的数据,或者作为从设备响应主设备的请求。例如,ESP32作为主设备读取连接的I2C传感器,并输出到串口。代码可能包括初始化I2C,扫描设备,发送请求,读取字节,处理数据等步骤。 调试部分,用户需要上传代码到ESP32,打开串口监视器查看输出,检查是否有数据正确读取,或者是否有错误发生,比如设备未连接,地址错误等。 可能的问题点包括:引脚连接是否正确,I2C地址是否正确,上拉电阻是否需要(通常I2C总线需要上拉电阻,但有些模块已经内置),时钟速度设置是否正确,以及代码中的逻辑错误,比如没有正确处理多字节读取等。 现在,用户的问题是关于ESP32Arduino之间的I2C通信,可能是指两个设备之间的通信,比如一个作为主,另一个作为从。例如,ESP32作为主设备,Arduino Uno作为从设备,或者反过来。这种情况下,代码需要双方都有对应的主从设置。例如,主设备发送请求,从设备返回数据。这可能需要编写两个部分的代码:一个用于主设备,另一个用于从设备。 例如,ESP32作为主设备,向Arduino从设备请求数据。Arduino从设备需要设置自己的I2C地址,并在接收到请求时发送数据。这可能涉及到Wire库的onReceive和onRequest事件处理函数的设置。 因此,在教程中可能需要包括主设备和从设备的代码示例,并说明如何连接两者的I2C线路(SDA接SDA,SCL接SCL,注意电压匹配,如果两个设备的工作电压不同,比如3.3V和5V,可能需要电平转换器)。 总结步骤: 1. 硬件连接:ESP32ArduinoI2C引脚连接,注意SDA和SCL交叉连接,共地,电压匹配。 2. 配置从设备(如Arduino Uno)设置I2C地址,并准备数据。 3. 配置主设备(ESP32)发送请求并接收数据。 4. 编写代码,使用Wire库进行通信。 5. 调试并测试通信是否成功。 可能还需要解释I2C地址的确定方法,比如使用I2C扫描代码来发现连接的设备地址。 最后,确保示例代码正确,包括必要的初始化和错误处理,比如检查是否成功接收到数据,或者在从设备没有响应时的处理。</think>### ESP32Arduino通过I2C通信的教程 #### 1. 硬件连接 - **ESP32ArduinoI2C引脚**: - ESP32默认I2C引脚:`SDA=GPIO21`,`SCL=GPIO22`(不同开发板可能需查阅手册)[^1]。 - Arduino Uno的I2C引脚:`SDA=A4`,`SCL=A5`。 - **连接方式**: - 将ESP32的SDA与Arduino的SDA连接,SCL与SCL连接。 - 共地:将两者的GND引脚相连。 - 若电压不同(如ESP32为3.3V,Arduino为5V),需使用电平转换模块。 #### 2. 代码实现 ##### 场景1ESP32作为主设备,Arduino作为从设备 **Arduino从设备代码(地址:0x08)**: ```cpp #include <Wire.h> void setup() { Wire.begin(0x08); // 设置从设备地址 Wire.onRequest(sendData); // 注册数据发送事件 } void sendData() { int value = analogRead(A0); // 读取模拟值 Wire.write(value >> 8); // 发送高字节 Wire.write(value & 0xFF); // 发送低字节 } void loop() { delay(100); } ``` **ESP32主设备代码**: ```cpp #include <Wire.h> void setup() { Serial.begin(115200); Wire.begin(); // 初始化I2C为主模式 } void loop() { Wire.requestFrom(0x08, 2); // 从地址0x08请求2字节数据 if (Wire.available() == 2) { uint8_t high = Wire.read(); uint8_t low = Wire.read(); int value = (high << 8) | low; Serial.print("Received: "); Serial.println(value); } delay(1000); } ``` ##### 场景2:扫描I2C设备地址(ESP32) ```cpp #include <Wire.h> void setup() { Serial.begin(115200); Wire.begin(); } void loop() { Serial.println("Scanning I2C devices..."); for (byte addr = 1; addr < 127; addr++) { Wire.beginTransmission(addr); if (Wire.endTransmission() == 0) { Serial.print("Found device at 0x"); Serial.println(addr, HEX); } } delay(5000); } ``` #### 3. 关键点说明 - **I2C地址**:从设备需设定唯一地址(1-127),可通过扫描代码确认。 - **数据传输**:多字节数据需分高低字节传输,主从设备需约定数据格式。 - **电平兼容**:若设备电压不同,需添加电平转换电路,避免损坏芯片。 #### 4. 调试建议 1. 先运行I2C扫描代码,确认设备地址。 2. 检查接线是否松动或接反。 3. 观察串口输出,若无数据,检查从设备是否响应请求。
评论 60
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值