ESP32S3+MSM261S4030H0+HT513 扬声器

去年使用ESP32S3+MSM261S4030H0+HT513 做了一个扬声器的项目。具体硬件设计可以在 https://oshwhub.com/arduinoai-hao-zhe/portable-speake 看到。

在使用的时候,遇到的一个问题就是MSM261S4030H0输出是32Bits(实际只有24Bits)。最近忽然想起来查了一下是否有机会按照 16Bits输出,搜索出来的资料说的是:只要设置 I2S Master按照16Bits 取即可。因为这个输出有效数据只有 24Bits,直接截断取前面的16Bit即可。

根据这个资料编写代码如下,工作正常。

#include <Arduino.h>
#include <Wire.h>
#include <driver/i2s.h>

#define I2S_PORT1 I2S_NUM_0
#define I2S_PORT2 I2S_NUM_1
#define SAMPLE_RATE 16000
#define CHANNEL_FORMAT I2S_CHANNEL_FMT_ONLY_LEFT
//#define BITS_PER_SAMPLE I2S_BITS_PER_SAMPLE_32BIT
#define BITS_PER_SAMPLE I2S_BITS_PER_SAMPLE_16BIT

#define MIC_BCK_PIN 37
#define MIC_WS_PIN 38
#define MIC_DATA_PIN 36

#define SPK_BCK_PIN 15
#define SPK_WS_PIN 6
#define SPK_DATA_PIN 7
#define SPK_MCK_PIN 16

// HT513 音量
uint16_t Volume;
#define TOLENCE 16
#define HT513_ADDR_L 0x6c
/**
   @brief  ht513写寄存器
   @param  addr 寄存器地址
   @param  val 要写的值
   @retval None
*/
void HT513_WriteOneByte(uint8_t addr, uint8_t val)
{
  Wire.beginTransmission(HT513_ADDR_L);
  Wire.write(addr);
  Wire.write(val);
  int ack = Wire.endTransmission(true);
  Serial.print("Ack ");
  Serial.println(ack, HEX);
}

/**
   @brief  ht513读寄存器
   @param  addr 寄存器地址
   @retval 读取到的寄存器值
*/
uint8_t HT513_ReadOneByte(uint8_t addr)
{
  uint8_t temp = 0;

  Wire.beginTransmission(HT513_ADDR_L);
  Wire.write(addr);
  Wire.endTransmission(false);
  uint8_t bytesReceived = 0;
  bytesReceived = Wire.requestFrom(HT513_ADDR_L, (uint8_t)1, true);
  if (bytesReceived == 1) {
    temp = Wire.read();
  }
  else {
    Serial.println("Read Error ");
  }

  return temp;
}

void setup() {
  Serial.begin(115200);

  delay(2000);

  i2s_config_t MIC_i2sConfig = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = BITS_PER_SAMPLE,
    .channel_format = CHANNEL_FORMAT,
    .communication_format = I2S_COMM_FORMAT_I2S,
    .intr_alloc_flags = 0,
    .dma_buf_count = 8,
    .dma_buf_len = 64,
    .use_apll = false,
    .tx_desc_auto_clear = false,
    .fixed_mclk = 0
  };

  i2s_pin_config_t MIC_pinConfig = {
    .bck_io_num = MIC_BCK_PIN,
    .ws_io_num = MIC_WS_PIN,
    .data_out_num = I2S_PIN_NO_CHANGE,
    .data_in_num = MIC_DATA_PIN
  };

  i2s_driver_install(I2S_PORT1, &MIC_i2sConfig, 0, NULL);
  i2s_set_pin(I2S_PORT1, &MIC_pinConfig);

  i2s_config_t SPK_i2sConfig = {
    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
    .sample_rate = SAMPLE_RATE,
    .bits_per_sample = BITS_PER_SAMPLE,
    .channel_format = CHANNEL_FORMAT,
    .communication_format = I2S_COMM_FORMAT_I2S,
    .intr_alloc_flags = 0,
    .dma_buf_count = 8,
    .dma_buf_len = 64,
    .use_apll = false,
    .tx_desc_auto_clear = false,
    .fixed_mclk = 0
  };

  i2s_pin_config_t SPK_pinConfig = {
    .mck_io_num = SPK_MCK_PIN, 
    .bck_io_num = SPK_BCK_PIN,
    .ws_io_num = SPK_WS_PIN,
    .data_out_num = SPK_DATA_PIN,
    .data_in_num = I2S_PIN_NO_CHANGE
  };

  i2s_driver_install(I2S_PORT2, &SPK_i2sConfig, 0, NULL);
  i2s_set_pin(I2S_PORT2, &SPK_pinConfig);

  analogReadResolution(9);
  Wire.begin(18, 17);
  //  设置 SD 为LOW
  HT513_WriteOneByte(0x12, 0b11110000);
  // 设置数据格式为 I2S, 16Bits
  HT513_WriteOneByte(0x13, 0b00110000);

  // 读取音量设置
  Volume = analogRead(3);
  uint8_t Vol = (Volume, 0, 511, 0x07, 0xff);
  HT513_WriteOneByte(0x16, Vol);
  HT513_WriteOneByte(0x15, Vol);
  Serial.println(Volume, HEX);

  // 调整声道
  HT513_WriteOneByte(0x17, 0b10110000);

  Serial.println("++++++++++++++++");
  //  设置 SD 为HIGH
  HT513_WriteOneByte(0x12, 0b11110100);
  uint8_t Value = HT513_ReadOneByte(0x12);
  Serial.println(Value, HEX);
  Value = HT513_ReadOneByte(0x13);
  Serial.println(Value, HEX);
  Value = HT513_ReadOneByte(0x16);
  Serial.println(Value, HEX);
  Value = HT513_ReadOneByte(0x17);
  Serial.println(Value, HEX);
Serial.print(" starting");
 // dsp.beginAEC(256, 1024, 16000); // Initialize AEC with frame size, filter length, and sample rate
 // dsp.enableAEC(true);            // Enable AEC
}

int8_t mic[512], speaker[521], out[512];
  
void loop() {
  size_t bytesRead = 0;
  
  i2s_read(I2S_PORT1, &mic, sizeof(mic), &bytesRead, portMAX_DELAY);
  i2s_write(I2S_PORT2, &mic, sizeof(mic), &bytesRead, portMAX_DELAY);

  if (abs(analogRead(3) - Volume) > TOLENCE) {
    // 读取音量设置
    Volume = analogRead(3);
    //  设置 SD 为LOW
    HT513_WriteOneByte(0x12, 0b11110000);
    uint8_t Vol = map(Volume, 0, 511, 0x07, 0xff);
    HT513_WriteOneByte(0x16, Vol);
    //  设置 SD 为HIGH
    HT513_WriteOneByte(0x12, 0b11110100);
    Serial.print(analogRead(3), HEX);
    Serial.print("  ");
    Serial.print(Volume, HEX);
    Serial.print("  ");
    Serial.println(Vol, HEX);
  }
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注