I2C接入指南*
主控芯片/上位机作为I2C Master设备,通过读写指定的地址和寄存器,可实现以下操作:
- 读取事件
- 复位
- 获取版本号
- 测试链路
GX8002提供了2个I2C Slave设备:0x2F
和0x36
,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
设备的中断寄存器0xC4
写0x68
分别依次读取寄存器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
设备的中断寄存器0xC4
写0x70
来获取麦克风的状态,读取寄存器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
设备的中断寄存器0xC4
写0x72
来打开Dmic,读取寄存器0xA0
的状态码,是否为0x72
向0x2F
设备的中断寄存器0xC4
写0x73
来关闭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的软件问题了