当前位置: 首页 > article >正文

通过IIC访问模块寄存器[ESP--1]

上一节中,我们简单使用ESP函数来从主机视角扫描所有的IIC设备|上一篇文章的链接|,但是并不存在主从机之间的交流。这显然是不合理的,这个小节我们来学习如何实现主从机之间的通信

模块的寄存器

不说最简单的电阻电容电感,稍微复杂一些的功能模块,显示屏,摄像头…他们是如何被主机控制的呢?他们内部其实存在着一系列寄存器,主机就是通过IIC来操作这些寄存器来控制模块的工作,下面我们还是以测距模块VL53L0X(淘宝大概8块到20块一个)做例子来看看如何使用IIC操作寄存器

coding

从官方文档可以知道VL53L0X下总共有这些常用的寄存器

#define VL53L0X_REG_IDENTIFICATION_MODEL_ID 0xc0

#define VL53L0X_REG_IDENTIFICATION_REVISION_ID 0xc2

#define VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD 0x50
#define VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD 0x70
#define VL53L0X_REG_SYSRANGE_START 0x00
#define VL53L0X_REG_RESULT_INTERRUPT_STATUS 0x13
#define VL53L0X_REG_RESULT_RANGE_STATUS 0x14
//设备IIC地址
#define address 0x29

我们这里先尝试读取一下前两个寄存器的内容

主从机通信示例
  • 要在通讯前正确的启动IIC设备

  • 使用Wire.write(reg),从主机向从机写入要读取的模块寄存器的地址

      Wire.beginTransmission(address);
      Wire.write(reg);
      Wire.endTransmission();
    
  • 然后下一步向从机请求若干个字节的值 Wire.requestFrom(address, int(1));

  • 下面一步就是读取,这一步也有一点要注意的东西,就是轮询可用的方案是比较有效的

    while (!Wire.available() );     // 等待数据可用
        return Wire.read();
    
#include <Wire.h>
#include <Arduino.h>
// VL53L0X 的 I2C 地址
#define VL53L0X_ADDRESS 0x29
#include <Adafruit_VL53L0X.h>
Adafruit_VL53L0X lox = Adafruit_VL53L0X();

byte readRegister(uint8_t address, uint8_t reg);

#define XSHUT_PIN 2

void setup() {
  Serial.begin(9600);
  Wire.begin();
  //别忘了设备的初始化
   // 初始化 XSHUT 引脚为输出
  pinMode(XSHUT_PIN, OUTPUT);
  // 启用传感器
  digitalWrite(XSHUT_PIN, HIGH);

  if (!lox.begin()) {
    Serial.println(F("Failed to boot VL53L0X"));
    while(1);
  }
}

void loop() {
  // 读取 VL53L0X_REG_IDENTIFICATION_MODEL_ID (寄存器地址 0xC0)
  byte model_id = readRegister(VL53L0X_ADDRESS, 0xC0);
  Serial.print("Model ID: 0x");
  Serial.println(model_id, HEX);

  // 读取 VL53L0X_REG_IDENTIFICATION_REVISION_ID (寄存器地址 0xC2)
  byte revision_id = readRegister(VL53L0X_ADDRESS, 0xC2);
  Serial.print("Revision ID: 0x");
  Serial.println(revision_id, HEX);

  delay(1000);
}

// 读取指定寄存器的函数
byte readRegister(uint8_t address, uint8_t reg) {
  Wire.beginTransmission(address);
  Wire.write(reg);
  Wire.endTransmission();

  Wire.requestFrom(address, int(1));
  while (!Wire.available() );     // 等待数据可用
    return Wire.read();
  /*
  最好轮询到值可用,这个方案不太行,万一不可用就不好了
   if (Wire.available()) {
    return Wire.read();
  } else {
    return 0xFF; // 错误值
  }
  */
}

下面是运行效果
在这里插入图片描述


http://www.kler.cn/a/406192.html

相关文章:

  • OpenCV双目立体视觉重建
  • 【进阶系列】python简单爬虫实例
  • tensorflow案例7--数据增强与测试集, 训练集, 验证集的构建
  • 基于 MUSA 的大语言模型推理和服务框架vLLM
  • 《C++ 实现区块链:区块时间戳的存储与验证机制解析》
  • 深入了解 Linux htop 命令:功能、用法与示例
  • springboot图书馆预约与占座小程序
  • RT-DETR融合[TIP2023]DehazeFormer中的SKFusion模块及相关改进思路
  • C++算法练习-day42——98.验证二叉搜索树
  • 31、js中日期操作
  • vulfocus在线靶场:CVE_2019_16662 速通手册
  • 耿恭坚守城池的方法
  • c++11的动态类型
  • 【AIGC】ChatGPT提示词Prompt解析:拒绝的艺术:如何优雅地说“不“
  • 如何为PDF文件创建口令密码
  • 如何在MATLAB中实现图像自动分割
  • C语言基础学习:抽象数据类型(ADT)
  • 远程服务器Docker使用本地代理加速访问外部资源
  • gitlab:使用脚本批量下载项目,实现全项目检索
  • 关于Linux中线程优先级的问题探讨
  • 【Linux】-学习笔记04
  • [ruby on rails] 安装docker
  • 量化交易系统开发-实时行情自动化交易-4.3.1.跨市场套利策略实现
  • JAVA中的Lamda表达式
  • Lua 实现继承的一种方式
  • n、nvm、nrm、pnpm、yarn各种指令大全