历遍单片机下的IIC设备[ESP--0]

IIC是常见的通讯协议,传输速度一般在100KB,很多的电子部件都是使用这个协议传输,了解它大有用处
简单来说,IIC只用两根线就能控制多个设备,相当简单好用

IIC使用的线分别为 SCL (serial clock 串行时钟线)和 SDA (serial data 串行数据线)

IIC的模式和地址

你可能会说,哎呀,这看上去也太难了,这让我怎么连线啊。没关系,打开你的单片机开发板引脚图,找到你支持IIC接口的那个GPIO,直接把SCL和SDA 怼到原件对应的引脚上就行了,然后使用封装好的库wire.h 引用个函数就配置好了(质疑PYTHON,理解PYTHON,成为PYTHON)

可以看到,ESP支持IIC ,GPIO21 和 GPIO 22分别是SDA和 SCL

地址问题

显然,一根IIC总线下可以接多个设备,为了通讯,每个设备都有自己的地址 (一般都被烧写进硬件中),标准的IIC设备是7位地址

下图A6:0是地址位,后面是读写位,所以理论上一根总线下,最多2^8=128个(设备范围是从0x010x7F),但是有些特殊地址是另作他用的,下面列出几个常用地址

使用IIC进行简单通信
  • #include <Wire.h> 要使用IIC的库 Wire.h
  • Wire.begin(); 使用前要初始化IIC总线(下面有解释)
  • Wire.beginTransmission(0x5A); 输入地址,向从机发信号
  • Wire.write(0x01); 向已经输入的地址发信
  • byte error = Wire.endTransmission();结束当前通信并获得通信状态 0 为成功的状态
CPP 复制代码
#include <Wire.h>
#include <Arduino.h>
//不载入Arduino.h,好像无法识别Serial  byte这个名字


void setup() {
  Wire.begin(); // 初始化 I2C 总线
  Serial.begin(9600);

  // 开始向地址为 0x5A 的 I2C 设备发送数据
  Wire.beginTransmission(0x5A);
  Wire.write(0x01);  // 写入数据
  Wire.write(0x02);  // 写入数据
  Wire.write(0x03);  // 写入数据
  byte error = Wire.endTransmission();  // 结束传输,并获取错误代码

  if (error == 0) {
    Serial.println("Data sent successfully!");
  } else {
    Serial.print("Failed to send data, error code: ");
    Serial.println(error);
  }
}

void loop() {
  // 循环代码
}

注意,这个程序仅仅做示例只用,你的设备地址不一定是5A,写入也可能没有用

Wire.begin();这个函数过程中发生了什么?

  1. 初始化 I2C 总线硬件

Wire.begin() 首先会初始化与 I2C 通信相关的硬件资源。这包括设置 I2C 控制器的时钟频率(通常为 100 kHz 或 400 kHz)、配置 SDA(数据线)和 SCL(时钟线)引脚的功能。没错,在ESP上就是配置GPIO21和GPIO22为IIC通信口

  1. 配置 I2C 控制器

I2C 控制器需要在开始通信之前进行配置。Wire.begin() 会设置控制器的模式(主机或从机),并配置相关的寄存器。

  • 主机模式 :当 Wire.begin() 没有参数时,Arduino 作为主机初始化 I2C 总线。
  • 从机模式 :当 Wire.begin(address) 带有参数时,Arduino 作为从机初始化 I2C 总线,并设置从机地址。
  1. 启动 I2C 总线

在初始化完成后,Wire.begin() 会启动 I2C 总线,使 Arduino 能够开始与其他设备进行通信。这包括设置起始条件(Start Condition),告诉其他设备准备开始通信。

  1. 清除总线状态

初始化过程中,Wire.begin() 还会清除任何可能存在的总线错误状态,确保总线处于干净、可通信的状态。

扫描IIC下的设备
  • 标准IIC的从机地址标号是7位,除去0号地址,总共是127个,挨个尝试呼叫即可
  • 在呼叫前,应该正确初始化IIC设备,否则没有应答是常态
  • 楼主这里用的是VL53L0X这个设备(距离传感器)

先CODE一下

CPP 复制代码
#include <Wire.h>
#include <Arduino.h>

void setup() {
  Wire.begin(); // 初始化 I2C 总线
  Serial.begin(9600);


  byte error;
  for (byte address = 1; address < 127; address++) {
    Wire.beginTransmission(address); // 使用循环中的address变量
    error = Wire.endTransmission(); // 结束传输,并获取错误代码

    if (error == 0) {
      Serial.print("address:");
      Serial.print(address, HEX);
      Serial.println("     Data sent successfully!");
    } else {
      Serial.print("Failed to send data to address ");
       Serial.print(address, HEX);
      Serial.print(", error code: ");
      Serial.println(error);
    }
  }
}

void loop() {

}

看看运行效果

bash 复制代码
Failed to send data to address , error code: 2
Failed to send data to address , error code: 2
Failed to send data to address , error code: 2
Failed to send data to address , error code: 2
Failed to send data to address , error code: 2
Failed to send data to address , error code: 2
Failed to send data to address , error code: 2

我去,怎么全部失败了?哦,我没有正确的启动IIC设备

cpp 复制代码
#include <Wire.h>
#include <Arduino.h>
#include <Adafruit_VL53L0X.h>

Adafruit_VL53L0X lox = Adafruit_VL53L0X();

// 定义 XSHUT 引脚
#define XSHUT_PIN 2
//如果你不希望使用GPIO 直接把它悬空,或者接地即可



void setup() {
  Wire.begin(); // 初始化 I2C 总线
  Serial.begin(9600);

  //要正确的初始化IIC设备,否则是检测不到的
    // 初始化 XSHUT 引脚为输出
  pinMode(XSHUT_PIN, OUTPUT);
  digitalWrite(XSHUT_PIN, LOW); // 初始状态为低电平

  // 启用传感器
  digitalWrite(XSHUT_PIN, HIGH);
  if (!lox.begin()) {
    Serial.println(F("Failed to boot VL53L0X"));
    while(1);
  }

  byte error;
  for (byte address = 1; address < 127; address++) {
    Wire.beginTransmission(address); // 使用循环中的address变量
    error = Wire.endTransmission(); // 结束传输,并获取错误代码

    if (error == 0) {
      Serial.print("address:");
      Serial.print(address, HEX);
      Serial.println("     Data sent successfully!");
    } else {
      Serial.print("Failed to send data to address ");
       Serial.print(address, HEX);
      Serial.print(", error code: ");
      Serial.println(error);
    }
  }
}

void loop() {
  // 循环代码(如果需要)
}
bash 复制代码
Failed to send data to address 28, error code: 2
address:29     Data sent successfully!
Failed to send data to address 2A, error code: 2
Failed to send data to address 2B, error code: 2
Failed to send data to address 2C, error code: 2

现在果然成功了,扫描到0x29 处有这个设备

相关推荐
梁朝辉3 小时前
STM32H750VBT6中ADCINP与INN什么区别
stm32·单片机·嵌入式硬件
省四收割者4 小时前
一文详解信号完整性(1)
python·嵌入式硬件·数学建模·信息与通信·信号处理·智能硬件
崇山峻岭之间5 小时前
单片机无感FOC驱动之ADC
单片机·嵌入式硬件
Ligocious5 小时前
1.点亮一颗小小的LED
单片机·嵌入式硬件
KaifuZeng9 小时前
通信与接口协议面试八、CAN通信
单片机·嵌入式硬件·面试·通信与接口协议
智源单片机设计10 小时前
基于单片机的直流电机双闭环调速系统设计
单片机·嵌入式硬件
KaifuZeng1 天前
通信与接口协议面试一、基本概念
嵌入式硬件·通信与接口协议
wuyk5551 天前
24. C 语言模块化:不是拆几个.c 文件那么简单
c语言·开发语言·stm32·单片机
☆cwlulu1 天前
调试排查工具介绍(gdb、strace、Valgrind等)
开发语言·c++·嵌入式硬件·ubuntu
lzqrzpt1 天前
LED驱动电源选型标准与工程应用技术要点解析
python·单片机·嵌入式硬件·物联网