连接测试

在I2C与控制器连接后,使用我的I2C教程中的扫描程序测试

测试后可以得到芯片的I2C地址为 0x4E

官方使用说明

双通道模拟输入设计

▽设计过程引用自TAA3020数据手册
  1. 为器件通电:
    1. 为 IOVDD 和 AVDD 电源上电
    2. 等待至少 1ms,让器件初始化内部寄存器
    3. 器件现在进入睡眠模式(低功耗模式 < 10µA)
  2. 每次录音操作需要时,从睡眠模式转换到工作模式:
    1. 通过写入 P0_R2 以禁用睡眠模式来唤醒器件
    2. 等待至少 1ms,让器件完成内部唤醒序列
    3. 根据需要覆盖默认配置寄存器或可编程系数值(这一步是可选操作)
    4. 通过写入 P0_R115 来启用所有需要的输入通道
    5. 通过写入 P0_R116 来启用所有需要的音频串行接口输出通道
    6. 通过写入 P0_R117 来为 ADC、MICBIAS 和 PLL 上电
    7. 施加具有所需输出采样速率和 BCLK 与 FSYNC 之比的 FSYNC 和 BCLK该特定步骤可以在步骤 a 后序列的任意时间点完成。有关支持的采样速率和 BCLK 与 FSYNC 之比,请参阅锁相环 (PLL) 和时钟生成 一节。
    8. 器件录音数据现在通过 TDM 音频串行数据总线发送到主机处理器
  3. 根据系统的低功耗运行要求,从工作模式(再次)转换到睡眠模式:
    1. 通过写入 P0_R2 以启用睡眠模式来进入睡眠模式
    2. 等待至少 6ms(FSYNC = 48kHz 时),让音量下降并让所有模块断电
    3. 读取 P0_R119 以检查器件关断和睡眠模式状态
    4. 如果器件 P0_R119_D7 状态位为 1'b1,则停止系统中的 FSYNC 和 BCLK
    5. 器件现在进入睡眠模式(低功耗模式 < 10µA)并保留所有寄存器值
  4. 根据录音操作需要,从睡眠模式(再次)转换到工作模式:
    1. 通过写入 P0_R2 以禁用睡眠模式来唤醒器件
    2. 等待至少 1ms,让器件完成内部唤醒序列
    3. 施加具有所需输出采样速率和 BCLK 与 FSYNC 之比的 FSYNC 和 BCLK
    4. 器件录音数据现在通过 TDM 音频串行数据总线发送到主机处理器
  5. 根据配置更改需要重复步骤 2 至步骤 4,或根据模式转换需要重复步骤 3 至步骤 4

板载麦克风配置

▽配置过程引用自TAA3020评估版使用手册

若要为这两个板载麦克风配置 ADC,请使用 PPC3 GUI 中的板载麦克风预设,或在 I2C 主应用程序中复制并粘贴以下脚本:

#####On-Board MIC Config######

w 9c 02 81 #Wake up device and enable AREG

w 9c 01 01 #Software Reset

d 100 #Wait 100ms

w 9c 00 00 #Set page 0

w 9c 02 81 #Wake up device and enable AREG

d 10 #wait 10 ms

w 9c 0d 01 #Set Ch-3 data to ASI left slot 1

w 9c 22 41 #Set IN2M_GPO1 to PDCMLK output (Default 3.072MHz)

w 9c 2b 50 #Set IN2P_GPI1 to PDMDIN2 for channel 3 and 4

w 9c 73 A0 #Enable input Ch-1 and Ch-3

w 9c 74 A0 # Enable ASI Output Ch-1 and Ch-3 slots

w 9c 75 E0 # Power-up ADC, MICBIAS and PLL

相关寄存器

▽简单初始化所需寄存器

7.2.2 SW_RESET 寄存器(地址 = 0x1)[复位 = 0x00]

字段类型复位说明
7-1RESERVEDR0b保留位;仅写入复位值
0SW_RESETR/W0b软件复位。此位可自行清除。
0d = 不复位
1d = 将所有寄存器复位为其复位值

7.2.3 SLEEP_CFG 寄存器(地址 = 0x2)[复位 = 0x00]

字段类型复位说明
7AREG_SELECTR/W0b从内部稳压器电源或外部 AREG 电源选择模拟电源。
0d = 外部 1.8V AREG 电源(当 AVDD 为 1.8V 且 AREG 与 AVDD 短接时使用该设置)
1d = 内部使用片上稳压器生成的 1.8V AREG 电源(当 AVDD 为 3.3V 时使用该设置)
6-5RESERVEDR0b保留位;仅写入复位值
4-3VREF_QCHG[1:0]R/W00bVREF 外部电容器的快速充电持续时间使用 200Ω 的内部串联电阻来设置。
0d = VREF 快速充电持续时间为 3.5ms(典型值)
1d = VREF 快速充电持续时间为 10ms(典型值)
2d = VREF 快速充电持续时间为 50ms(典型值)
3d = VREF 快速充电持续时间为 100ms(典型值)
2I2C_BRDCAST_ENR/W0bI2C 广播寻址设置。
0d = 禁用 I2C 广播模式
1d = 启用 I2C 广播模式;I2C 目标地址固定为 1001 100
1RESERVEDR0b保留位;仅写入复位值
0SLEEP_ENZR/W0b睡眠模式设置。
0d = 器件处于睡眠模式
1d = 器件未处于睡眠模式

7.2.50 IN_CH_EN 寄存器(地址 = 0x73)[复位 = 0xC0]

字段类型复位说明
7IN_CH1_ENR/W1b输入通道 1 使能设置。
0d = 通道 1 禁用
1d = 通道 1 启用
6IN_CH2_ENR/W1b输入通道 2 使能设置。
0d = 通道 2 禁用
1d = 通道 2 启用
5IN_CH3_ENR/W0b输入通道 3(仅限 PDM)使能设置。
0d = 通道 3 禁用
1d = 通道 3 启用
4IN_CH4_ENR/W0b输入通道 4(仅限 PDM)使能设置。
0d = 通道 4 禁用
1d = 通道 4 启用
3-0RESERVEDR0b保留位;仅写入复位值

7.2.51 ASI_OUT_CH_EN 寄存器(地址 = 0x74)[复位 = 0x00]

字段类型复位说明
7ASI_OUT_CH1_ENR/W0bASI 输出通道 1 启用设置。
0d = 通道 1 输出时隙处于三态条件
1d = 通道 1 输出时隙已启用
6ASI_OUT_CH2_ENR/W0bASI 输出通道 2 启用设置。
0d = 通道 2 输出时隙处于三态条件
1d = 通道 2 输出时隙已启用
5ASI_OUT_CH3_ENR/W0bASI 输出通道 3 启用设置。
0d = 通道 3 输出时隙处于三态条件
1d = 通道 3 输出时隙已启用
4ASI_OUT_CH4_ENR/W0bASI 输出通道 4 启用设置。
0d = 通道 4 输出时隙处于三态条件
1d = 通道 4 输出时隙已启用
3-0RESERVEDR0b保留位;仅写入复位值

7.2.52 PWR_CFG 寄存器(地址 = 0x75)[复位 = 0x00]

字段类型复位说明
7MICBIAS_PDZR/W0bMICBIAS 的电源控制。
0d = MICBIAS 断电
1d = MICBIAS 上电
6ADC_PDZR/W0bADC 和 PDM 通道的电源控制。
0d = 所有 ADC 和 PDM 通道断电
1d = 所有已启用的 ADC 和 PDM 通道上电
5PLL_PDZR/W0bPLL 的电源控制。
0d = PLL 断电
1d = PLL 上电
4DYN_CH_PUPD_ENR/W0b动态通道上电/断电使能。
0d = 如果任何通道录音处于开启状态,则不支持通道上电/断电
1d = 即使通道录音处于开启状态,通道也可以单独上电或断电
3-2DYN_MAXCH_SEL[1:0]R/W00b动态模式最大通道选择配置。
0d = 启用动态通道上电/断电功能时使用通道 1 和通道 2
1d = 启用动态通道上电/断电功能时使用通道 1 至通道 4
2d = 保留;不使用
3d = 保留;不使用
1RESERVEDR0b保留位;仅写入复位值
0VAD_ENR/W0b启用语音活动检测 (VAD) 算法。
0d = 禁用 VAD
1d = 启用 VAD
▽状态寄存器

7.2.53 DEV_STS0 寄存器(地址 = 0x76)[复位 = 0x00]

字段类型复位说明
7CH1_STATUSR0bADC 或 PDM 通道 1 电源状态。
0d = ADC 或 PDM 通道断电
1d = ADC 或 PDM 通道上电
6CH2_STATUSR0bADC 或 PDM 通道 2 电源状态。
0d = ADC 或 PDM 通道断电
1d = ADC 或 PDM 通道上电
5-0RESERVEDR0b保留位;仅写入复位值

7.2.54 DEV_STS1 寄存器(地址 = 0x77)[复位 = 0x80]

字段类型复位说明
7-5MODE_STS[2:0]R100b器件模式状态。
4d = 器件处于睡眠模式或软件关断模式
6d = 器件处于工作模式且所有 ADC 或 PDM 通道都关闭
7d = 器件处于工作模式且至少一个 ADC 或 PDM 通道开启
4-0RESERVEDR0b保留位;仅写入复位值

芯片主模式初始化配置

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

static constexpr uint8_t ADDRESS = 0x4E;

/**
 * @brief 写数据到I2C设备
 *
 * @param reg 要写入的寄存器地址
 * @param data 要写入的数据
 * @return true
 * @return false
 */
bool i2cWrite(uint8_t reg, uint8_t data) {
  Wire.beginTransmission(ADDRESS);
  Wire.write(reg);
  Wire.write(data);
  return Wire.endTransmission();
}

/**
 * @brief 从I2C设备读取数据
 *
 * @param reg 要读取的寄存器地址
 * @return uint8_t 读取到的数据
 */
uint8_t i2cRead(uint8_t reg) {
  Wire.beginTransmission(ADDRESS);
  Wire.write(reg);
  Wire.endTransmission();
  Wire.requestFrom((uint8_t)ADDRESS, (uint8_t)0x01);
  return Wire.read();
}

void setup() {
  Serial0.begin(115200);
  Wire.begin(8, 9, 100000);  // I2C初始化
  i2cWrite(0x02, 0x81);      // 关闭睡眠
  i2cWrite(0x01, 0x01);      // 重启复位
  delay(100);
  i2cWrite(0x00, 0x00);  // 配置寄存器页0
  i2cWrite(0x02, 0x81);  // 关闭睡眠
  delay(10);
  i2cWrite(0x73, 0xc0);  // 开启通道1、2
  i2cWrite(0x74, 0xc0);  // 开启ASI输出通道1、2
  i2cWrite(0x75, 0xe0);  // 开启MICBIAS、ADC、PLL电源

  Serial0.print("0x76: ");
  Serial0.println(i2cRead(0x76), HEX);  // 读取状态寄存器1
  Serial0.print("0x77: ");
  Serial0.println(i2cRead(0x77), HEX);  // 读取状态寄存器2
}

void loop() {}

完成配置后发现串口打印 0x76: 0 ; 0x77: c0
理应不该如此,暂时没有找到问题,等待后续实验更新

I2S配置

注意查看数据手册中

参考测试代码(尚无数据处理内容,仅提供时序参考与数据查看,等待后续更新)

使用个人编写的I2S库,Arduino提供的并不好用

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

CL_I2S_LIB taa3020(0, taa3020.MASTER, taa3020.RX, taa3020.PCM);  // 创建I2S对象

static constexpr uint8_t ADDRESS = 0x4E;
static constexpr uint32_t SAMPLE_RATE = 8000;  // 采样率(WS频率)
static constexpr uint8_t BPS = 32;             // 采样位数

static int32_t readData[1440];

bool i2cWrite(uint8_t reg, uint8_t data) {
  Wire.beginTransmission(ADDRESS);
  Wire.write(reg);
  Wire.write(data);
  return Wire.endTransmission();
}

uint8_t i2cRead(uint8_t reg) {
  Wire.beginTransmission(ADDRESS);
  Wire.write(reg);
  Wire.endTransmission();
  Wire.requestFrom((uint8_t)ADDRESS, (uint8_t)0x01);
  return Wire.read();
}

void setup() {
  Serial0.begin(115200);
  Serial0.println("Serial0 Init OK");
  Wire.begin(8, 9, 100000);

  i2cWrite(0x02, 0x81);
  i2cWrite(0x01, 0x01);
  delay(100);
  i2cWrite(0x00, 0x00);  // 配置寄存器页0
  i2cWrite(0x02, 0x81);
  delay(10);
  i2cWrite(0x73, 0xc0);
  i2cWrite(0x74, 0xc0);
  i2cWrite(0x75, 0xe0);

  taa3020.begin(SAMPLE_RATE, BPS);                     // 初始化I2S
  taa3020.setFormat(taa3020.RIGHT_LEFT, taa3020.I2S);  // 设置I2S格式
  taa3020.setDMABuffer(4, 480);                        // 设置DMA缓冲区大小
  taa3020.install(17, 18, 19);                         // 安装I2S引脚,启动I2S

  Serial0.println("I2S Init OK");

  memset(readData, 0, sizeof(readData));
  delay(1000);
  taa3020.Read(readData, 1440);  // 读取I2S接收到的数据存入数组
  for (size_t i = 0; i < 1440; i++) {
    Serial0.println(readData[i]);  // 串口打印数组中的数据
  }
}

void loop() {}