连接Mic并设置I2S后工作不正常,想请教下是不是我参数设置有误。
已知信息:
Mic输出的音频为24位大端数据,为标准Philips格式(数据延后一个clk),且要求channel为32位宽(datasheet要求SCK频率为WS的64倍)。
现象:
使用逻辑分析仪抓包发现每个channel的sck数量始终等于代码中定义的采样深度(bits_per_sample),与通道深度无关(bits_per_chan)。例如(bits_per_sample=24,bits_per_chan=32)时抓包发现左声道只有24个clk,bits_per_sample=16时左声道只有16个clk。
抓包结果如图,实际在左声道时只有16个clk出来。 预期效果:
如图,预期应该在每个通道设置有32个clk出来,但是实际只采样最前面的24(16)个bit到内存中,下图效果是将bits_per_sample 设置为32时得到的,但是这样设置的话,虽然每个channel是32bit了,但是采样到的最低一个字节为无意义的信号(mic在第24bit发出后就高阻态了),浪费宝贵的空间不说,需要软件再做处理,又要浪费cpu时间。 此外,我也尝试了(代码中注释掉的)i2s_set_clk,使用该函数后也同样无法将channel的深度设置为32。
Code: Select all
// ESP_ERROR_CHECK(i2s_set_clk(I2S_MIC_BUS_PORT, I2S_MIC_SAMPLE_RATE, (I2S_BITS_PER_CHAN_32BIT << 16) | I2S_BITS_PER_SAMPLE_24BIT, I2S_CHANNEL_MONO));
/* You can reset parameters by calling 'i2s_set_clk'
*
* The low 16 bits are the valid data bits in one chan and the high 16 bits are
* the total bits in one chan. If high 16 bits is smaller than low 16 bits, it will
* be set to a same value as low 16 bits.
*/
uint32_t bits_cfg = (I2S_BITS_PER_CHAN_32BIT << 16) | I2S_BITS_PER_SAMPLE_16BIT;
i2s_set_clk(i2s_num, 22050, bits_cfg, I2S_CHANNEL_STEREO);
根据现象推断,设置的bits_per_chan未起到作用,请问是我哪里设置有问题还是这是IDF中/硬件中的问题?
如果是代码参数设置问题,请指出如何实现所需功能(bits_per_chan的意义何在,如何使用)。
如果是库或者硬件问题,请指点下哪个版本的IDF或芯片解决了这个问题。
感激不尽
环境:
IDF:v5.0-dev-595-g98ad01e5fc
Mic:INMP441 24bit I2S
MCU:ESP32-WROOM-32U (rev版本暂未查,可能比较老,但errata里未找到相关信息,应该不重要)
不重要的环境(Win10+VisualStudio2022,供电使用IdealDiode线或了USB与外部电源)
- #define IO_IIS_WS ((gpio_num_t)16)
- #define IO_IIS_SCK ((gpio_num_t)4)
- #define IO_IIS_SD ((gpio_num_t)17)
- #define I2S_MIC_BUS_PORT ((i2s_port_t)I2S_NUM_1)
- #define I2S_MIC_SAMPLE_RATE 22050 // old 44100
- // Left aligned 24bit data
- // skip first rising clock
- // 32bit per channel
- const int I2S_BLOCK_SIZE = 16;
- #define MIC_FRAME_SIZE 4
- void microphone_init(void) {
- i2s_config_t i2s_config{};
- i2s_config.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX);
- i2s_config.sample_rate = I2S_MIC_SAMPLE_RATE;
- i2s_config.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT; // mic provides 24bit data, but, I should able to only sample the high 2bytes?(I've changed this to 24bits, it wont work either)
- i2s_config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT;
- i2s_config.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S); // skip first rising clock, so it's Philips standard i2s
- i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL2;
- i2s_config.dma_buf_count = 8;
- i2s_config.dma_buf_len = I2S_BLOCK_SIZE * MIC_FRAME_SIZE;
- i2s_config.use_apll = false;
- i2s_config.bits_per_chan = I2S_BITS_PER_CHAN_32BIT; // mic datasheet says it needs the channel bits be 32bits (64 sclk per ws cycle) (32bits channel width > 24bits sample width, so it should have 32bits per channel, right?)
- i2s_pin_config_t pin_config{};
- pin_config.mck_io_num = I2S_PIN_NO_CHANGE;
- pin_config.bck_io_num = IO_IIS_SCK;
- pin_config.ws_io_num = IO_IIS_WS;
- pin_config.data_out_num = I2S_PIN_NO_CHANGE;
- pin_config.data_in_num = IO_IIS_SD;
- ESP_ERROR_CHECK(i2s_driver_install(I2S_MIC_BUS_PORT, &i2s_config, 0, NULL));
- ESP_ERROR_CHECK(i2s_set_pin(I2S_MIC_BUS_PORT, &pin_config));
- // ESP_ERROR_CHECK(i2s_set_clk(I2S_MIC_BUS_PORT, I2S_MIC_SAMPLE_RATE, (I2S_BITS_PER_CHAN_32BIT << 16) | I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO));
- ESP_ERROR_CHECK(i2s_zero_dma_buffer(I2S_MIC_BUS_PORT));
- }