I2C Lidar 更改地址

问题描述 投票:0回答:1

我在更改激光雷达传感器的地址时遇到问题。它的默认地址是 7 位的 0x62,但由于微控制器只需要 8 位,所以地址现在是 0xC4。这是我写的代码:

void change_address(char new_addr)
{
    char addr = 0x16;
    char tab[2];
   
    i2c.write(LIDAR_ADDR,&addr, 1);
    i2c.read(LIDAR_ADDR,tab,2);
  
    char tab1[2] = {0x18,0};
    tab1[1] = tab[0];

    i2c.write(LIDAR_ADDR,tab1,2);

    char tab2[2] = {0x19,0};
    tab2[1] = tab[1];
    
    i2c.write(LIDAR_ADDR,tab2,2);

    char tab3[2] = {0x1a,new_addr};

    i2c.write(LIDAR_ADDR,tab3,2);

    char tab4[2] = {0x1e,0x08};

    i2c.write(LIDAR_ADDR,tab4,2);
}

Steps for changing the address

我已经按照所有步骤操作了,但是当我要查看新地址时,我分配的新地址不存在。有谁知道原因吗?提前谢谢你

我做了这段代码来检查 I2C 组件是否存在,这段代码在激光雷达传感器的默认地址下运行良好,但当我尝试更改激光雷达的地址时它不再起作用

int main() {

  int i;
  int rep;
  printf("Debut du Scan...\n\r");
  char new_add = 0x46 << 1;
  change_address(new_add);   
  for (i = 0x00; i <= 0xFF; i = i + 1) 
  {
    i2c.start();       // Start
    rep = i2c.write(i); // Envoi d’une adresse, y a-t-il une
    if (rep == 1)             // réponse ?
    {
      printf("Test de l’adresse %x Composant I2C present !!\n\r", i);
    } 
    else 
    {
        printf("Test de l’adresse %x ... rien ... \n\r",i);
    }
    i2c.stop(); // Stop
    wait(0.1);
  }
  printf("Fin du Scan...\n\r");
}
c++ c robotics mbed lidar
1个回答
1
投票

我认为你误解了 I2C 的工作原理。 I2C 地址默认为 7 位(有 10 位模式,但我们将在此处忽略),但是为了执行 I2C 通信,您所做的是让主机/主机通过 I2C 启动(设置 SDA /SCL 电平适当),然后传输控制字节(由 7 位 I2C 地址 + 1 位组成,指示您是否正在使用读/写操作,因此对于写入,这将是

(0x62 << 1) | 0
(
0xc4
),对于读取将是
(0x62 << 1) | 1
0xc5
)),等待总线上的设备确认该控制字节,然后读取总线上的数据(将每个字节作为主机确认,最后一个字节除外)或进一步发送字节(并等待总线上每个设备的 ACK),最后发送一个 I2C 停止序列。

此外,与大多数I2C设备的交互通常是这样的:你首先要发送一个或多个字节表示你要与之交互(读/写)的设备上的寄存器,然后你才真正执行写/读操作.如果要向设备写入数据,这很简单:首先传输控制字节,然后传输寄存器,然后将要写入的数据传输到该寄存器。如果您正在从设备读取数据,它会变得更加复杂,因为您首先必须在发送寄存器的地方启动写操作(但寄存器没有数据),然后重新启动 I2C 序列以启动读操作到读取该寄存器的数据。

我不完全知道你在这里使用的是哪个 I2C 库,但是通过阅读你的代码,我怀疑你会想要做类似下面的事情来改变设备的地址(我也抽象了读/编写寄存器函数,以便在与设备自身通信时可以重复使用这些函数;请注意,它们假设您始终有一个字节用于寄存器,一个字节用于寄存器数据——如果您想与其他 I2C 设备通信,这可能会有所不同——你必须阅读那里的文档):

// Read a register from the I2C device
//    This implementation will write the register index
//    to the I2C device and then read the resulting
//    value. (This only works for I2C devices that
//    follow this very addressing scheme.)
//
// Parameters:
//    i2c_addresss: The 7bit (!) I2C address of the device
//    device_register: The 8bit device register to read
//
// Return value:
//    The device register
unsigned char read_register(unsigned char i2c_address, unsigned char device_register)
{
    i2c.start();
    // send control byte (writing data)
    bool rep = i2c.write((i2c_address << 1) | 0);
    if (!rep) {
        i2c.stop();
        // feel free to do any kind of error handling you like here
        throw std::runtime_error("I2C transaction failed");
    }
    // send the register we want to read to the device
    rep = i2c.write(device_register);
    if (!rep) {
        i2c.stop();
        // feel free to do any kind of error handling you like here
        throw std::runtime_error("I2C transaction failed");
    }
    // now we want to read from the I2C device
    // for this we restart the I2C transaction
    // Note: most I2C devices don't require an
    //       I2C stop before the next I2C start
    //       here, but feel free to insert one
    //       if this doesn't work with your device
    i2c.start();
    // send control byte (reading data)
    bool rep = i2c.write((i2c_address << 1) | 1);
    if (!rep) {
        i2c.stop();
        // feel free to do any kind of error handling you like here
        throw std::runtime_error("I2C transaction failed");
    }
    // now I'm only guessing how your I2C library works...
    // no idea if i2c.read() actually looks this way in your case...
    unsigned char result = i2c.read();
    i2c.stop();
}

// Write a register to the I2C device
//     This implementation will write the register index, followed
//     by the register value, to the I2C device. (This only works
//     for I2C devices that follow this very addressing scheme.)
//
// Parameters:
//    i2c_addresss: The 7bit (!) I2C address of the device
//    device_register: The 8bit device register to read
//    value: The register value to write
void write_register(unsigned char i2c_address, unsigned char device_register, unsigned char value)
{
    i2c.start();
    // send control byte (writing data)
    bool rep = i2c.write((i2c_address << 1) | 0);
    if (!rep) {
        i2c.stop();
        // feel free to do any kind of error handling you like here
        throw std::runtime_error("I2C transaction failed");
    }
    // send the register we want to write to the device
    rep = i2c.write(device_register);
    if (!rep) {
        i2c.stop();
        // feel free to do any kind of error handling you like here
        throw std::runtime_error("I2C transaction failed");
    }
    // send the value of the register to the device
    rep = i2c.write(value);
    if (!rep) {
        i2c.stop();
        // feel free to do any kind of error handling you like here
        throw std::runtime_error("I2C transaction failed");
    }
    i2c.stop();
}

void update_address_of_lidar(unsigned char new_address)
{
    // This is the 7bit (!) address of the device
    unsigned char orig_address = 0x62;

    // read out the serial number of the I2C device
    unsigned char sn_high = read_register(orig_address, 0x16);
    unsigned char sn_low = read_register(orig_address, 0x17);

    // re-write the serial number of the device to unlock
    // the corresponding register
    write_register(orig_address, 0x18, sn_high);
    write_register(orig_address, 0x19, sn_low);

    // write the new i2c address to the device
    write_register(orig_address, 0x1a, new_address);

    // attempt to re-read the serial number from the new
    // address (to see if assignment has worked)
    unsigned char sn_high2 = read_register(new_address, 0x16);
    unsigned char sn_low2 = read_register(new_address, 0x17);
    if (sn_high2 != sn_high || sn_low2 != sn_low) {
        // feel free to do any kind of error handling you like here
        throw std::runtime_error("Could not update the I2C address successfully");
    }

    // Now that we know the new address works we can disable
    // the default address
    // (Note that while the instructions of the manual say
    // to write 0x08 here, the register documentation for
    // the register 0x1e indicates that 0x01 disables the
    // original I2C address. So if the following doesn't
    // work to disable the original address, you can also
    // try 0x01 here...)
    write_register(orig_address, 0x1e, 0x08);
}

// Other code:

// NB: if you want the new control byte for writing
//     to be 0x46, then the corresponding 7bit (!)
//     address would actually be 0x23
unsigned char new_address = 0x46;

update_address_of_lidar(new_address);

标准免责声明:

  • 我不知道你使用的是什么 I2C 库,这里的代码主要是猜测它是如何使用的。可能是我用错了你的 I2C 库,因为我根本不知道你用的是哪个。
  • 我没有你的激光雷达设备,所以我根本无法测试这个。
  • 如果您将它与另一个 I2C 设备一起使用,其中所讨论的寄存器有其他含义,您可能会损坏该硬件,具体取决于这些寄存器的作用。
  • 以上代码仅供参考,不提供任何保证。使用风险自负。
  • 根据您的 I2C LIDAR 设备的文档,设备将在下次再次开机时忘记您在此处设置的地址。因此,我不太明白您为什么要首先更改地址。 (除非您使用多个设备并且有一个 GPIO 引脚控制 LIDAR 设备的启用引脚。)
  • 我在互联网上找到了您的 LIDAR 设备的完整手册(如果有人想知道):https://forum.arduino.cc/uploads/short-url/8ZYkVAsROHL2dnqKxsz2qGSFHvz.pdf
© www.soinside.com 2019 - 2024. All rights reserved.