Page 1 of 1

求助 I2S Master bits_per_sample != bits_per_chan 情况下工作不正常

Posted: Wed Jan 05, 2022 12:10 pm
by fanhuanji
问题描述:
连接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出来。
屏幕截图 2022-01-05 195731.png
实际效果
屏幕截图 2022-01-05 195731.png (23.56 KiB) Viewed 3852 times
预期效果
如图,预期应该在每个通道设置有32个clk出来,但是实际只采样最前面的24(16)个bit到内存中,下图效果是将bits_per_sample 设置为32时得到的,但是这样设置的话,虽然每个channel是32bit了,但是采样到的最低一个字节为无意义的信号(mic在第24bit发出后就高阻态了),浪费宝贵的空间不说,需要软件再做处理,又要浪费cpu时间。
屏幕截图 2022-01-05 195227.png
期望效果
屏幕截图 2022-01-05 195227.png (31.08 KiB) Viewed 3852 times
此外,我也尝试了(代码中注释掉的)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));
根据IDF的doc所述,set_clk方法的第三个参数的高16位用于指示channel有多少个bits宽,低16bit用于指示channel里的数据有多少个bit宽,但是实测并没有产生等于高16位所指示的数量的clk。
/* 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与外部电源)
  1. #define IO_IIS_WS      ((gpio_num_t)16)
  2. #define IO_IIS_SCK     ((gpio_num_t)4)
  3. #define IO_IIS_SD      ((gpio_num_t)17)
  4. #define I2S_MIC_BUS_PORT   ((i2s_port_t)I2S_NUM_1)
  5. #define I2S_MIC_SAMPLE_RATE 22050 // old 44100
  6.  
  7. // Left aligned 24bit data
  8. // skip first rising clock
  9. // 32bit per channel
  10. const int I2S_BLOCK_SIZE = 16;
  11. #define MIC_FRAME_SIZE 4
  12. void microphone_init(void) {
  13.   i2s_config_t i2s_config{};
  14.   i2s_config.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX);
  15.   i2s_config.sample_rate = I2S_MIC_SAMPLE_RATE;
  16.   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)
  17.   i2s_config.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT;
  18.   i2s_config.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S); // skip first rising clock, so it's Philips standard i2s
  19.   i2s_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL2;
  20.   i2s_config.dma_buf_count = 8;
  21.   i2s_config.dma_buf_len = I2S_BLOCK_SIZE * MIC_FRAME_SIZE;
  22.   i2s_config.use_apll = false;
  23.   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?)
  24.  
  25.   i2s_pin_config_t pin_config{};
  26.   pin_config.mck_io_num = I2S_PIN_NO_CHANGE;
  27.   pin_config.bck_io_num = IO_IIS_SCK;
  28.   pin_config.ws_io_num = IO_IIS_WS;
  29.   pin_config.data_out_num = I2S_PIN_NO_CHANGE;
  30.   pin_config.data_in_num = IO_IIS_SD;
  31.  
  32.   ESP_ERROR_CHECK(i2s_driver_install(I2S_MIC_BUS_PORT, &i2s_config, 0, NULL));
  33.   ESP_ERROR_CHECK(i2s_set_pin(I2S_MIC_BUS_PORT, &pin_config));
  34.   // 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));
  35.  
  36.   ESP_ERROR_CHECK(i2s_zero_dma_buffer(I2S_MIC_BUS_PORT));
  37. }