侧边栏壁纸
  • 累计撰写 125 篇文章
  • 累计创建 16 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录
ESP32   

ESP32-I2C简要理解

概述

I2C是一种串行,同步,半双工通信协议,允许在同一总线上同时存在多个主机和从机。I2C总线由两条线组成:串行数据线(SDA)和串行时钟(SCL)。两条线都需要上拉电阻。

I2C总线由两条线组成:串行数据线(SDA)和串行时钟(SCL)。两条线都需要上拉电阻。

ESP32有两个I2C控制器(也称为端口),负责处理两条I2C总线上的通信。每个I2C控制器都可以作为主机或从机运行。例如,一个控制器可以同时充当主控制器,另一个可以充当从控制器。

I2C通信规则

这里我不介绍底层的脉冲发送与接收时序规则,既然选择了Arduino开发,则是越简单越好~

SDA 与 SCL

大致理解一下这俩是干啥的,SCL(时钟线)简单理解就是只要启动就啥也不管,无脑的按照设定频率发出‘PWM波’,使连在同一SCL的设备同步,同一个心跳~

SDA(数据线)单根的串行数据线,串行的意思就是,数据按位一个接一个串起来,再挨个发出去。然后我们约定一个标准,根据两根线的高低电平的搭配,有序的完成数据收发。

主设备往从设备中写数据(大哥下任务)

放心不讲底层时序~先讲小故事。大哥给小弟在微信群下指令,大哥首先打开微信群,@一下小弟,小弟赶紧回复‘在’,然后大哥下一个任务,小弟嗯一声表示收到了,可以连着下好几个任务,下完任务后大哥让小弟快去执行把。

对应到I2C的通讯规则也是一样的,主设备(大哥)先往SDA线上发出从设备地址(@小弟,其中还包含了是大哥下任务还是小弟汇报工作的标志位),从设备发现是给自己下指令赶紧回复,接着主设备发送指令内容到结束。

主设备从从设备中读数据(小弟汇报工作)

同样大哥要小弟在微信群里汇报一下工作,大哥首先打开微信群,@一下小弟,小弟赶紧回复‘在’,然后逐一汇报工作,大哥嗯一声表示知道了,可以连着汇报好几个任务,汇报后大哥表示滚吧~

对应到I2C的通讯规则也是一样的,主设备(大哥)先往SDA线上发出从设备地址(@小弟,其中还包含了是大哥下任务还是小弟汇报工作的标志位),从设备发现是给自己下指令赶紧回复,接着从设备发送指令内容到结束。

Arduino层编程

这里使用的是Wire工具。首先看看它的公共类,看看它提供了哪些API接口:

public:
    TwoWire(uint8_t bus_num);
    ~TwoWire();
    bool begin(int sda=-1, int scl=-1, uint32_t frequency=0); // 初始化设置,配置引脚

    void setClock(uint32_t frequency); // 改变工作频率
    size_t getClock(); // 查看当前工作频率

    void setTimeOut(uint16_t timeOutMillis); // 设置溢出时间,默认是50ms
    uint16_t getTimeOut(); // 查看当前溢出时间

    uint8_t lastError();  // 错误查看
    char * getErrorText(uint8_t err);

    //@stickBreaker for big blocks and ISR model
    i2c_err_t writeTransmission(uint16_t address, uint8_t* buff, uint16_t size, bool sendStop=true);  // 
    i2c_err_t readTransmission(uint16_t address, uint8_t* buff, uint16_t size, bool sendStop=true, uint32_t *readCount=NULL);

    void beginTransmission(uint16_t address); // @小弟~
    void beginTransmission(uint8_t address);
    void beginTransmission(int address);

    uint8_t endTransmission(bool sendStop); // 结束对话
    uint8_t endTransmission(void);

    uint8_t requestFrom(uint16_t address, uint8_t size, bool sendStop); // @小弟让他汇报
    uint8_t requestFrom(uint16_t address, uint8_t size, uint8_t sendStop);
    uint8_t requestFrom(uint16_t address, uint8_t size);
    uint8_t requestFrom(uint8_t address, uint8_t size, uint8_t sendStop);
    uint8_t requestFrom(uint8_t address, uint8_t size);
    uint8_t requestFrom(int address, int size, int sendStop);
    uint8_t requestFrom(int address, int size);

    size_t write(uint8_t); // 下任务
    size_t write(const uint8_t *, size_t);
    int available(void);
    int read(void);  // 大哥听汇报
    int peek(void);
    void flush(void);

    void onReceive( void (*)(int) );
    void onRequest( void (*)(void) );

    uint32_t setDebugFlags( uint32_t setBits, uint32_t resetBits);
    bool busy();

例子(DHT12)

**注意:这个地址,这8位地址中最后一位是用于判断写\读操作的,在API中会自动添加,所以我们在传递地址时,直接发送设备的地址即可,不用画蛇添足的自己加上最后一位。

#include <Arduino.h>
#include <Wire.h>

#define DHT12_zy (0xB8 >> 1) // I2C bus address

void setup() {
    Serial.begin(9600);
    Wire.begin(21,22);
}

void loop() {
  delay(1000);
  byte value0,value1,value2, value3;

  Wire.beginTransmission(DHT12_zy); 
  Wire.write(0x00); 
  Wire.endTransmission();
  Wire.requestFrom(DHT12_zy, 2);
  value0=Wire.read();

  Wire.beginTransmission(DHT12_zy); 
  Wire.write(0x01);
  Wire.endTransmission(); 
  Wire.requestFrom(DHT12_zy, 2);
  value1=Wire.read();

  Wire.beginTransmission(DHT12_zy);
  Wire.write(0x02); 
  Wire.endTransmission(); 
  Wire.requestFrom(DHT12_zy, 2);
  value2=Wire.read();
  
  Wire.beginTransmission(DHT12_zy);
  Wire.write(0x03); 
  Wire.endTransmission();
  Wire.requestFrom(DHT12_zy, 2);
  value3=Wire.read();

 Serial.print("湿度"); Serial.print(value0); Serial.print(".");
 Serial.print(value1); Serial.print(" ");

 Serial.print("温度"); Serial.print(value2); Serial.print(".");
 Serial.print(value3); Serial.print(" ");
}
0

评论区