跳转至

I2C接入指南*

主控芯片/上位机作为I2C Master设备,通过读写指定的地址和寄存器,可实现以下操作:

  • 读取事件
  • 复位
  • 获取版本号
  • 测试链路

GX8002提供了2个I2C Slave设备:0x2F0x36,2个设备在同一总线上,共用一组SCL和SDA引脚:

设备地址 寄存器 (8bit data) 说明 操作
0x2F 0xA0, 0xA4, 0xA8, 0xAC 数据寄存器,用于存放事件,状态,参数等数据 Read/Write
0xC4 中断寄存器,向该寄存器写入非零数据将触发GX8002中断 Write
0xB0 复位寄存器,向该寄存器写入1将复位GX8002,但是该复位不会清一些I2C0自己的寄存器。如果仅仅B0写01在某些情况下,会复位失败。完整的做法需要:I2C地址2F,寄存器9C 写A5;D0写5A;CC写04;B0写01 可以实现任何情况下的复位 Write
0x36 固件下载通道 Write

GX8002遵循标准7 bit地址的I2C操作方式:

  • Write

  • Read

  • Write / Read with repeated start

对于带寄存器的slave设备,需以Wirte模式发送寄存器地址来指定要操作的寄存器。特别地,针对读取操作,在发送寄存器地址后,需通过repeated start信号切换到Read模式

1. 设备地址*

使用 7 位地址,为:0x2F。

读数据的话,读写位为 0,因此 7位地址 + 读写位0 为 0x5E

写数据的话,读写位为 1,因此 7位地址 + 读写位1 为 0x5F

2. 读取事件*

2.1 读取事件*

  • 通过读取0x2F设备的指定寄存器0xA0来获取事件

  • 读到有效事件需向中断寄存器0xC4写入 Confirm 信息

  • 如不及时读取事件,新事件将会覆盖旧事件

  • 在具体方案中,可使用轮询或者响应外接 GPIO 中断的方式来读取事件

2.2 语音事件*

GX8002检测到语音激活词或者短指令会产生语音事件

  • 寄存器: 0xA0
  • Confirm: 0x10
  • EventID (同GX8002短指令ID):
ID 事件
100 主唤醒词
102 暂停播放
103 停止播放
104 播放音乐
105 增大音量
106 减小音量
112 播放上一首
113 播放下一首
114 接听电话
115 挂掉电话

注意

上面事件的 ID 值会根据具体固件而不同,需要和对应工程师沟通确认

2.3 代码示例*

void gx8002_read_voice_event(void)
{
    unsigned char event_id = 0;

    // read voice evevnt: addr = 0x2f, reg = 0xa0
    // 只读一个字节长度
    i2c_rx_reg(0x2f, 0xa0, &event_id, 1); // 平台i2c的接口,和具体平台相关,这里给出伪代码
    if(event_id > 0)
    {
        unsigned char confirm = 0x10;
        // confirm: addr = 0x2f, reg = 0xc4, value = 0x10
        // 清空事件,只写一个字节长度
        i2c_tx_reg(0x2f, 0xc4, &confirm, 1); // 平台i2c的接口,和具体平台相关,这里给出伪代码
        printf("I get voice event ID = %d\n", event_id);
    }
}

2.4 波形示例*

这里读到的事件是:0x64,十进制就是 100

3. 复位*

3.1 复位*

0x2F设备的寄存器0xB0写入1可复位GX8002

完整的做法应该是:I2C地址2F,寄存器9C 写A5;D0写5A;CC写04;B0写01 可以实现复位

注意

如果是 OTA 的过程,务必使用硬件复位的方法。因为这个复位方法是软件复位,必须软件功能正常的时候才可用。考虑到 OTA 过程出现异常,设备变砖,那么要重新升级,就只能硬件复位。

3.2 代码示例*

void gx8002_reset(void)
{
    unsigned char val = 1;

    i2c_tx_reg(0x2f, 0x9c, &val, 0xa5);
    i2c_tx_reg(0x2f, 0xd0, &val, 0x5a);
    i2c_tx_reg(0x2f, 0xcc, &val, 0x04);

    // reset: addr = 0x2f, reg = 0xb0, value = 1
    i2c_tx_reg(0x2f, 0xb0, &val, 0x01);
}

3.3 波形示例*

4. 获取版本号*

4.1 获取版本号*

0x2F设备的中断寄存器0xC40x68分别依次读取寄存器0xA0,0xA4,0xA8,0xAC数据得到版本号

获取到的数据例如:0x01,0x02,0x03,0x4 对应V1.2.3.4

4.2 代码示例*

void gx8002_get_verstion(void)
{
    unsigned char val = 1;
    unsigned char verstion[4] = {0,0,0,0};
    unsigned char reg = 0xa0;

    i2c_tx_reg(0x2f,0xc4,&val,0x68);
    //适当加点延时,因为8002收到指令后,写寄存器也需要时间,如果立刻读寄存器,高概率读取不到正确的值
    mdaly(200);
    for(int i = 0; i < 4; ++i){
        i2c_rx_reg(0x2f, reg, &ver, 1);
        verstion[i] = ver;
        reg += 4;
    }
}

4.3 波形示例*

5. 获取麦克风状态*

5.1 获取麦克风状态*

0x2F设备的中断寄存器0xC40x70来获取麦克风的状态,读取寄存器0xA0的状态码

  • 0xA0状态码:
码值 说明
0 异常
1 正常

5.2 代码示例*

void gx8002_get_mic_state(void)
{
    unsigned char val = 1;
    int mic_state = 0;
    unsigned char reg = 0xa0;

    i2c_tx_reg(0x2f,0xc4,&val,0x70);
    //适当加点延时,因为8002收到指令后,写寄存器也需要时间,如果立刻读寄存器,高概率读取不到正确的值
    mdaly(200);    
    i2c_rx_reg(0x2f, reg, &ver, 1);
    mic_state = ver;
}

5.3 波形示例*

6. 测试链路*

6.1 测试链路*

  • 0x2F设备的中断寄存器0xC4写入0x80触发GX8002测试链路中断

  • 读取0xAC寄存器,读到1测试成功

  • 测试成功后,需向中断寄存器0xC4写入确认信息0x11

6.2 代码示例*

int gx8002_test_link(void)
{
    unsigned char i2c_irq;
    unsigned char val = 0;
    int tick_cnt = 100;

    i2c_irq = 0x80;
    i2c_tx_reg(0x2f, 0xc4, &i2c_irq, 1);

    while(tick_cnt--) {
        gx_os_sleep(10);
        i2c_rx_reg(0x2f, 0xac, &val, 1);
        if(val == 1) {
            i2c_irq = 0x11;
            i2c_tx_reg(0x2f, 0xc4, &i2c_irq, 1);
            printf("i2c link ok !\n");
            break;
        }
    }

    return val;
}

7. 开关Dmic功能*

7.1 开关Dmic功能*

0x2F设备的中断寄存器0xC40x72来打开Dmic,读取寄存器0xA0的状态码,是否为0x72

0x2F设备的中断寄存器0xC40x73来关闭Dmic,读取寄存器0xA0的状态码,是否为0x73

7.2 代码示例*

int gx8002_open_dmic(void)
{
    unsigned char i2c_open_dmic_irq = 0x72;
    unsigned char val = 0;
    int tick_cnt = 100;

    i2c_tx_reg(0x2f, 0xc4, &i2c_open_dmic_irq, 1);

    while(tick_cnt--) {
        gx_os_sleep(10);
        i2c_rx_reg(0x2f, 0xa0, &val, 1);
        if(val == i2c_open_dmic_irq) {
            printf("open dmic ok !\n");
            break;
        }
    }

    return 0;
}

int gx8002_close_dmic(void)
{
    unsigned char i2c_close_dmic_irq = 0x73;
    unsigned char val = 0;
    int tick_cnt = 100;

    i2c_tx_reg(0x2f, 0xc4, &i2c_close_dmic_irq, 1);

    while(tick_cnt--) {
        gx_os_sleep(10);
        i2c_rx_reg(0x2f, 0xa0, &val, 1);
        if(val == i2c_close_dmic_irq) {
            printf("close dmic ok !\n");
            break;
        }
    }

    return 0;
}

8. 接入注意事项*

  • 确保设备地址正确,我们的是 7 位地址,0x2F。需要客户根据自己平台的 I2C 接口传入正确的地址。有的平台驱动接口要求传入 8 位(自己补充上读写位),有的平台驱动接口要求传入 7 位,驱动会自己补充上读写位
  • I2C 通讯,务必在 GX8002 上电后并稳定工作了,再交互。一般等 GX8002 上电,1-2秒后进行交互
  • 测试的时候,先保证 GX8002 的固件是支持 I2C 通讯协议的固件,没有的话,和工程师沟通获取。另外,要保证测试的过程,GX8002 是正常运行的。接触 GX8002 的串口,通过打印来确认 Gx8002 固件是否支持 I2C,是否在正常工作中。推荐前期调试使用我们的开发板,避免硬件设备和固件不匹配的问题,导致调试异常
  • 设备地址也正确了,硬件和固件也都没有问题了,还是调试不通。参考我们提供的波形示例,请在SOC的I2C端,测量波形,看和我们的示例是否一致。如果不一致,那么确认驱动是否使用正确或者周边硬件干扰。如果都正确了,还是不通,那么测量GX8002端的I2C,看看波形是否和示例的一致。如果不正确,确认周边是否存在硬件干扰。因为在前面使用了开发板调试,并且通过的话,就可以在这个阶段排除Gx8002的软件问题了