我正在尝试使用 I2S 直接来自 ADC 的功能,以立体声方式运行。我正在使用在 Ubuntu 18.04 上开发的 Wemos Lolin D32,它使用 ESP32-WROOM-32。
我的 IDF 版本是 v3.3-beta2,但它需要对 IDF 进行一些修改才能公开必要的功能(我也通过直接操作寄存器尝试过);我将在下面详细说明。
我的问题是,无论我做什么,我都会看到 ADC 数据加倍或跳过通道。我有从 I2S 读取的 ADC 数据中提取通道的代码,如下所示:
代码:
sta
tic void show_some_data(uint16_t * data)
{
const unsigned rows = 8;
for (unsigned row = 0; row < rows; row++)
{
ESP_LOGI(
TAG,
"CH: %d %d %d %d %d %d %d %d",
(data[8*row + 0] & 0xF000) >> 12,
(data[8*row + 1] & 0xF000) >> 12,
(data[8*row + 2] & 0xF000) >> 12,
(data[8*row + 3] & 0xF000) >> 12,
(data[8*row + 4] & 0xF000) >> 12,
(data[8*row + 5] & 0xF000) >> 12,
(data[8*row + 6] & 0xF000) >> 12,
(data[8*row + 7] & 0xF000) >> 12
);
}
}
我在串行日志中看到的结果是:
代码:
I (324) I2S: PLL_D2: Req RATE: 24000, real rate: 1515.000, BITS: 16, CLKM: 55, BCK: 60, MCLK: 55.556, SCLK: 48480.000000, diva: 64, divb: 35
I (334) i2s-test: CH: 6 6 6 6 6 6 0 0
I (334) i2s-test: CH: 0 0 0 0 0 0 0 0
I (344) i2s-test: CH: 0 0 0 0 0 0 0 0
I (344) i2s-test: CH: 0 0 0 0 0 0 0 0
I (354) i2s-test: CH: 0 0 0 0 0 0 0 0
I (354) i2s-test: CH: 0 0 0 0 0 0 0 0
I (364) i2s-test: CH: 0 0 0 0 0 0 0 0
I (364) i2s-test: CH: 0 0 0 0 0 0 0 0
I (364) i2s-test: CH: 5 5 6 6 5 5 6 6
I (374) i2s-test: CH: 5 5 6 6 5 5 6 6
I (374) i2s-test: CH: 5 5 6 6 5 5 6 6
I (384) i2s-test: CH: 5 5 6 6 5 5 6 6
I (384) i2s-test: CH: 5 5 6 6 5 5 6 6
I (394) i2s-test: CH: 5 5 6 6 5 5 6 6
I (394) i2s-test: CH: 5 5 6 6 5 5 6 6
I (394) i2s-test: CH: 5 5 6 6 5 5 6 6
I (404) i2s-test: CH: 6 6 5 5 6 6 5 5
配置相当简单:
代码:
i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN,
.sample_rate = SAMPLE_RATE, // 24kHz
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.communication_format = I2S_COMM_FORMAT_I2S,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 2,
.dma_buf_len = NUM_SAMPLES, // 64
.use_apll = 0,
.fixed_mclk = 0
};
i2s_driver_install(i2s_num, &i2s_config, 4, i2s_queue);
i2s_set_clk(i2s_num, SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_STEREO);
i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_6);
adc_set_i2s_data_pattern(ADC_UNIT_1, 0, ADC_CHANNEL_6, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11);
adc_set_i2s_data_pattern(ADC_UNIT_1, 1, ADC_CHANNEL_5, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11);
adc_set_i2s_data_len(ADC_UNIT_1, 2);
正如我提到的,我必须对 IDF 进行一些更改才能使用 ADC 模式表:公开函数 adc_set_i2s_data_len() 和 adc_set_i2s_data_pattern() 并注释掉 i2s_adc_enable() 中的 _i2s_adc_mode_recover() 调用。生成的代码在 我的 fork 中可用。
它可以通过检查并执行“idf.py build”来构建。
我完全无法弄清楚出了什么问题。我检查了我的代码和 IDF 库以确保正确设置了寄存器。我已经从头到尾阅读了技术参考手册。我已经尝试过使用和不使用队列,使用和不使用 DMA 清除。我已经使用示波器来验证 WS 信号确实以 24kHz 的频率运行(尽管这不应该影响通道顺序)。
即使只是让其他人尝试我的示例项目并告诉我他们是否在他们的硬件上看到相同的东西,这对我来说也是一个巨大的帮助。但是,如果您看到我在这里犯的一个错误,或者对更多调试有任何想法,请告诉我。