c语言 - 调用函数时 ESP32 上存储禁止i2s_read错误



我正在尝试在我的 esp32 微控制器上使用麦克风传感器。目前,它运行的是 ESP-IDF 框架。麦克风是sph0645lm4h-b。我正在使用 I2S 协议连接到传感器。

I2S 配置如下所示:

void i2s_init()
{
i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_RX, // I2S_MODE_TX Only TX
.sample_rate = 17000,
.bits_per_sample = 32,
// .channel_format = I2S_CHANNEL_FMT_ALL_LEFT, //2-channels
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
.dma_buf_count = 8,
.dma_buf_len = 64,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 //Interrupt level 1
};
i2s_pin_config_t pin_config = {
.bck_io_num = 26,
.ws_io_num = 25,
.data_out_num = -1, //Not used
.data_in_num = 27
};
i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM, &pin_config);
}

收集数据的代码:

i2s_init(); //initializes mics 
int samples_value, samples_data;
samples_value = i2s_pop_sample(I2S_NUM, &samples_data, 2);
printf("%d,", samples_data);

当我将代码上传到微控制器时,我得到的数据令人困惑。输出从真正的负值和 1 交替。

数据:

-191725568,1,-191823872,1,-191889408,1,-192020480,1,-192118784,1,-190152704,1,-190054400,1,-190021632,1

我不确定这是否是我应该从麦克风传感器接收的数据,我在 I2S 文档中读到i2s_pop_sample已贬值,所以我尝试使用该i2s_read但我收到 StoreProhibition 错误。

i2s_read代码:

int *samples;
int s;
samples = &s;       //pointer initialization
i2s_read(I2S_NUM,&samples,4,4,2); 

错误:

Guru Meditation Error: Core  0 panic'ed (StoreProhibited). Exception was unhandled.
Core 0 register dump:
PC      : 0x400d7552  PS      : 0x00060b30  A0      : 0x800d1c9f  A1      : 0x3ffcc950
A2      : 0x00000000  A3      : 0x3ffccaa8  A4      : 0x00000004  A5      : 0x00000004
A6      : 0x00000002  A7      : 0x00000005  A8      : 0x800d1e72  A9      : 0x3ffcc900
A10     : 0x3d87e746  A11     : 0x00000000  A12     : 0x00000001  A13     : 0x00000002
A14     : 0x7f800000  A15     : 0x00000000  SAR     : 0x00000015  EXCCAUSE: 0x0000001d
EXCVADDR: 0x00000004  LBEG    : 0x40002390  LEND    : 0x4000239f  LCOUNT  : 0x00000000
Backtrace: 0x400d7552:0x3ffcc950 0x400d1c9c:0x3ffcc990 0x400e9994:0x3ffccae0

我只是要解决i2s_read()问题,因为i2s_pop_sample()已被弃用。

调用i2s_read()的方式是使用指针作为数据缓冲区,并将整数作为指针传递。

以下是 ESP-IDF 手册中i2c_read()原型。

esp_err_t i2s_read(i2s_port_ti2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait)
  • i2s_num是 i2s 端口号
  • dest是将数据读入的缓冲区的地址
  • 缓冲区的大小size
  • bytes_read是一个指向size_t的指针,该指针将写入读取的字节数
  • ticks_to_wait是超时

您传递给i2s_read()的参数有两个问题。你这样称呼它:

int *samples;
int s;
samples = &s;
i2s_read(I2S_NUM,&samples,4,4,2); 

传递&samples作为缓冲区的地址。所以你告诉i2s_read()的是读取 4 字节的数据并将它们存储在samples中,这没有多大意义,因为它是一个指针。您应该只传递&s作为缓冲区,并跳过与samples的胡闹。

第二个问题是你传递4作为bytes_read参数。我真的很惊讶这甚至编译了。这使得i2s_read()尝试存储地址 4 处读取的字节数的size_t,这肯定会导致某种异常。

试试这个:

int32_t sample;
size_t bytes_read;
i2s_read(I2S_NUM, &sample, 4, &bytes_read, 2); 

这:

  1. 不假设int的存储大小,并保证sample的 4 字节(32 位)整数
  2. 正确传递指向创建的 4 字节整数的指针,该整数用于保存i2s_read()读取的数据
  3. 正确地传递指向size_t的指针,以便i2s_read()可以存储它读取的字节数。

如果你想知道实际读取了多少字节,那就是bytes_read.

最新更新