乐鑫技术交流
直播中

bigbangboom

8年用户 1269经验值
擅长:电源/新能源
私信 关注
[问答]

I2S Master bits_per_sample != bits_per_chan情况下工作不正常是怎么回事?

问题描述:
连接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。
// 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与外部电源)


  • #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));
  • }



回帖(1)

李鸿洋

2024-6-19 16:20:04
从您的描述来看,问题可能出在I2S配置上。在I2S通信中,bits_per_sample 和 bits_per_chan 是两个不同的概念:

1. bits_per_sample:每个采样点的位数,即每个音频样本的数据宽度。在您的例子中,Mic输出的音频为24位大端数据。

2. bits_per_chan:每个通道的数据宽度。在您的例子中,datasheet要求channel为32位宽。

根据您的描述,逻辑分析仪抓包结果显示每个channel的sck数量始终等于bits_per_sample,而不是bits_per_chan。这可能导致数据传输不完整或错误。

为了解决这个问题,您可以尝试以下步骤:

1. 检查I2S配置:确保您的I2S配置正确地设置了bits_per_sample和bits_per_chan。根据您的描述,bits_per_sample应为24,bits_per_chan应为32。

2. 检查时钟配置:确保SCK频率设置正确。根据您的描述,SCK频率应为WS的64倍。检查您的时钟配置是否满足这个要求。

3. 检查数据对齐:由于Mic输出的是24位大端数据,确保您的I2S配置正确地处理了数据对齐。这可能需要在接收端进行一些额外的处理,以确保数据正确地对齐到32位通道宽度。

4. 检查数据接收逻辑:确保您的数据接收逻辑能够正确地处理bits_per_sample和bits_per_chan。这可能包括在接收到每个采样点后,将其扩展到bits_per_chan的宽度。

5. 使用调试工具:使用逻辑分析仪或其他调试工具,仔细检查I2S通信过程中的数据和时钟信号。这可以帮助您找到问题所在,并确保数据传输正确。

通过以上步骤,您应该能够找到问题所在并解决I2S通信不正常的问题。如果问题仍然存在,请检查硬件连接和Mic本身是否存在问题。
举报

更多回帖

×
20
完善资料,
赚取积分