最近突发奇想,制作一个数字式的音频通信系统,顺便学习一下I2S与ESP-NOW协议

刚开始查阅资料,发现油管上的已经有人做过了,但是使用的C++,并用了数据流的处理流程,比较晦涩难懂,代码量也很大,属于是炫技的作品,我这篇文章使用C重新写一遍,并且代码量大大降低,也很容易理解,let's get started!

上一篇博客中已经详细讲解了I2S通信协议,在ESP32中有两个硬件I2S,我们可以通过简单的配置使用它

ESP-NOW是乐鑫的私有协议,相比于传统的七层协议,ESP-NOW只保留了物理层与数据连接层,在其之上封装了ESP-NOW协议,但是这个协议是不开源的,意味着我们看不到这个协议的源码,只能使用封装出来的接口。

1.png

使用的硬件:
麦克风:INMP441
功放:MAX98357
主控:ESP32*2
按键与指示灯:板载

使用的软件:
Arduino IDE
ESP32扩展包 2.0.4(最新)

编程思路:
发送:初始化I2S采集后,数据会源源不断的存放在DMAbuf中,按下按键,将数据取出,转换成需要的格式,最终转换成8bit数据发送出去。
接受:在ESP-NOW接受回调函数中,将接收到的数据重新转换为16位, 发送到I2S中的DMA去。注意,在没有接收到消息的是否,需清空dambuf,要不然会重复播放上一帧的音频,发出很大的噪音。
数据流向:I2S采集->原始32bit->16bit->8bit->esp-now发送->接收到数据8bit->转换为16bit->I2S播放

具体配置:
麦克风采集配置

const i2s_config_t rec_i2s_config = {
      .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
      .sample_rate = SAMPLE_RATE,
      .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
      .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
      .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S| I2S_COMM_FORMAT_I2S_MSB),
      .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
      .dma_buf_count = 2,
      .dma_buf_len = 256,
}

扬声器采集配置:

const i2s_config_t spk_i2s_config = {
      .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
      .sample_rate = SAMPLE_RATE,
      .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
      .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
      .communication_format =(i2s_comm_format_t)(I2S_COMM_FORMAT_I2S),
      .intr_alloc_flags = 0,
      .dma_buf_count = 2,
      .dma_buf_len = 256,
};

其中,dambuf的两个参数的设定比较有讲究,可以点击这里学习

硬件连接:
INMP441:
BCK --->>>IO4
WS --->>>IO15
data--->>>IO13

MAX98357:
BCK --->>>IO26
WS --->>>IO22
data--->>>IO25

开源github链接,点击我