当前位置: 首页 > article >正文

ESP-IDF学习记录(6)

这篇不知道起什么标题,因为已经卡滞很久了,从年前到现在,但也没停止探索

1.烧录

用的小型加热台,这步对我来说最难,自己没有焊接过QFN32的封装

总结一下目前遇到的问题:

1)5V供电选成了12V转5V芯片,电脑USb口只有5V,能工作,但是不稳定

2)qfn32,16pintypec对于我这种新手来说还是不太好焊接

3)usb下载有问题,目前没找到解决办法。因为实物没有焊接usb转串口部分,所以我是把串口脚直接接到外部ttl转usb上进行下载。或者直接焊接串口电路下载。

4)uart0还是乐鑫芯片首选验证方式,自己设计板子需要保留,并且与调试相关的都要设计成焊接针脚引出

5)下次设计要装上2P的typec接口,专门供电使用

好歹是主芯片运行起来了,氛围灯亮了,详情见:

蛇年RGB律动收音机 - 立创开源硬件平台蛇年RGB律动收音机,RGB随着收音机播放律动。支持usb或者串口烧录。主要是做块板子研究ESP-IDF框架的,学习软件是关键https://oshwhub.com/houyawei/year-of-the-snake-atmosphere-lamicon-default.png?t=O83Ahttps://oshwhub.com/houyawei/year-of-the-snake-atmosphere-lam不过硬件其他部分还是有问题

2.WiFi测试

这部分测试正常,但是信号不好,板子放在电脑主机上不容易连到WiFi。

用开发板测试没有这个问题。

说明天线布置的有问题,主芯片可以正常工作。

3.音频驱动

ES8311目前是我遇到最大的问题,使用官方idf 的demo,会崩溃,显示的i2c写入或者读取失败。

问题记录在乐鑫论坛上:

When running the demo of i2S ES8311, it crashes - ESP32 ForumEspressif ESP32 Official Forumicon-default.png?t=O83Ahttps://www.esp32.com/viewtopic.php?f=13&t=44240运行i2S ES8311的demo时,崩溃 - ESP32 ForumEspressif ESP32 Official Forumicon-default.png?t=O83Ahttps://www.esp32.com/viewtopic.php?f=25&t=44239运行i2S ES8311的demo时,崩溃了

es8311_init()就出问题了
es8311_write_reg i2c全报错,I2C read/write error
但是运行demo i2c tool,可以正常读写ES8311的寄存器,读到的地址是0x18U。
请教一下需要从哪判断问题。
试过ESP IDF5.3.2,ESP IDF5.1.4都是一样的问题。




i2s es8311 codec example start
-----------------------------
I (363) i2s_es8311: i2s driver init success
E (1363) ES8311: es8311_init(329): I2C read/write error
ESP_ERROR_CHECK failed: esp_err_t 0x107 (ESP_ERR_TIMEOUT) at 0x42007890
--- 0x42007890: es8311_codec_init at E:/ESPproject/i2s_es8311/main/i2s_es8311_example.c:61 (discriminator 1)

file: "./main/i2s_es8311_example.c" line 61


在i2c tool里面都是正常的

i2c-tools> i2cdetect
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- 18 -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
i2c-tools> i2cset -c 0x18 -r 0x00 0x1A
I (538875) cmd_i2ctools: Write OK
i2c-tools>  i2cget -c 0x18 -r 0x00 -l 1
0x1a 
i2c-tools> i2cset -c 0x18 -r 0x00 0x2B
I (570835) cmd_i2ctools: Write OK
i2c-tools>  i2cget -c 0x18 -r 0x00 -l 1
0x2b


i2c tool的i2c在5.1.3上用的旧驱动


#include "driver/i2c.h"

在5.3.2上用的新驱动

#include "driver/i2c_master.h"

测试起来都正常
i2s es8311里面一直是旧的I2C

#include "driver/i2c.h"

在论坛也发现别的用户发此类帖子了

i2s_es8311 example not working with ESP32-S3-LCD-EV-Board - ESP32 Forumi2s_es8311 example not working with ESP32-S3-LCD-EV-Boardi2s_es8311 example not working with ESP32-S3-LCD-EV-Board - ESP32 Forum

不得不说乐鑫论坛是真的拉跨,发帖子没人理,过年的时候论坛一直有问题,搜索就未反应。

在隔壁STC发的帖子永远有人回应,有的时候只是大佬的顺嘴一提,就能解决我这种小喽啰的大问题。

后面就不用es8311的组件,使用codec试了试

用了codec之后起码是不崩溃了,i2c也可以成功加载了,但是i2s没有数据,这点是有可能的,因为我的焊接技术很拉,qfn焊接不上很正常

/*
 * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: CC0-1.0
 */

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "esp_idf_version.h"
#include "unity.h"
#include "esp_codec_dev.h"
#include "esp_codec_dev_defaults.h"

#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
#include "driver/i2s_std.h"
#include "driver/i2s_tdm.h"
#include "soc/soc_caps.h"
#else
#include "driver/i2s.h"
#endif

#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) && !CONFIG_CODEC_I2C_BACKWARD_COMPATIBLE
#include "driver/i2c_master.h"
#define USE_IDF_I2C_MASTER
#else
#include "driver/i2c.h"
#endif


#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
#define I2S_MAX_KEEP SOC_I2S_NUM
typedef struct {
    i2s_chan_handle_t tx_handle;
    i2s_chan_handle_t rx_handle;
} i2s_keep_t;

static i2s_comm_mode_t i2s_in_mode = I2S_COMM_MODE_STD;
static i2s_comm_mode_t i2s_out_mode = I2S_COMM_MODE_STD;
static i2s_keep_t *i2s_keep[I2S_MAX_KEEP];
#endif

static void codec_max_sample(uint8_t *data, int size, int *max_value, int *min_value)
{
    int16_t *s = (int16_t *) data;
    size >>= 1;
    int i = 1, max, min;
    max = min = s[0];
    while (i < size) {
        if (s[i] > max) {
            max = s[i];
        } else if (s[i] < min) {
            min = s[i];
        }
        i++;
    }
    *max_value = max;
    *min_value = min;
}

static int ut_i2c_init(uint8_t port)
{
#ifdef USE_IDF_I2C_MASTER
    i2c_master_bus_config_t i2c_bus_config = {0};
    i2c_bus_config.clk_source = I2C_CLK_SRC_DEFAULT;
    i2c_bus_config.i2c_port = port;
    i2c_bus_config.scl_io_num = TEST_BOARD_I2C_SCL_PIN;
    i2c_bus_config.sda_io_num = TEST_BOARD_I2C_SDA_PIN;
    i2c_bus_config.glitch_ignore_cnt = 7;
    i2c_bus_config.flags.enable_internal_pullup = true;
    return i2c_new_master_bus(&i2c_bus_config, &i2c_bus_handle);
#else
    i2c_config_t i2c_cfg = {
        .mode = I2C_MODE_MASTER,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = 100000,
    };
    i2c_cfg.sda_io_num = GPIO_NUM_0;
    i2c_cfg.scl_io_num = GPIO_NUM_1;
    esp_err_t ret = i2c_param_config(port, &i2c_cfg);
    if (ret != ESP_OK) {
        return -1;
    }
    return i2c_driver_install(port, i2c_cfg.mode, 0, 0, 0);
#endif
}

static int ut_i2s_init(uint8_t port)
{
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
    if (port >= I2S_MAX_KEEP) {
        return -1;
    }
    // Already installed
    if (i2s_keep[port]) {
        return 0;
    }
    i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
    i2s_std_config_t std_cfg = {
        .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(16000),
        .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(16, I2S_SLOT_MODE_STEREO),
        .gpio_cfg ={
            .mclk = GPIO_NUM_10,
            .bclk = GPIO_NUM_8,
            .ws = GPIO_NUM_12,
            .dout = GPIO_NUM_11,
            .din = GPIO_NUM_7,
        },
    };
    i2s_keep[port] = (i2s_keep_t *) calloc(1, sizeof(i2s_keep_t));
    if (i2s_keep[port] == NULL) {
        return -1;
    }
#if SOC_I2S_SUPPORTS_TDM 
    i2s_tdm_slot_mask_t slot_mask = I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3;
    i2s_tdm_config_t tdm_cfg = {
        .slot_cfg = I2S_TDM_PHILIPS_SLOT_DEFAULT_CONFIG(16, I2S_SLOT_MODE_STEREO, slot_mask),
        .clk_cfg  = I2S_TDM_CLK_DEFAULT_CONFIG(16000),
        .gpio_cfg = {
            .mclk = GPIO_NUM_10,
            .bclk = GPIO_NUM_8,
            .ws = GPIO_NUM_12,
            .dout = GPIO_NUM_11,
            .din = GPIO_NUM_7,
        },
    };
    tdm_cfg.slot_cfg.total_slot = 4;
#endif
    int ret = i2s_new_channel(&chan_cfg, &i2s_keep[port]->tx_handle, &i2s_keep[port]->rx_handle);
    if(ret == ESP_OK)  printf("i2s_new_channel success.\n");
    else printf("i2s_new_channel failed.\n");
    if (i2s_out_mode == I2S_COMM_MODE_STD) {
        ret = i2s_channel_init_std_mode(i2s_keep[port]->tx_handle, &std_cfg);
    }
#if SOC_I2S_SUPPORTS_TDM 
    else if (i2s_out_mode == I2S_COMM_MODE_TDM) {
        ret = i2s_channel_init_tdm_mode(i2s_keep[port]->tx_handle, &tdm_cfg);
    }
#endif
    if(ret == ESP_OK)  printf("2 success.\n");
    else printf("2 failed.\n");
    if (i2s_in_mode == I2S_COMM_MODE_STD) {
        ret = i2s_channel_init_std_mode(i2s_keep[port]->rx_handle, &std_cfg);
    } 
#if SOC_I2S_SUPPORTS_TDM 
    else if (i2s_in_mode == I2S_COMM_MODE_TDM) {
        ret = i2s_channel_init_tdm_mode(i2s_keep[port]->rx_handle, &tdm_cfg);
    }
#endif
    if(ret == ESP_OK)  printf("3 success.\n");
    else printf("3 failed.\n");
    // For tx master using duplex mode
    i2s_channel_enable(i2s_keep[port]->tx_handle);
#else
    i2s_config_t i2s_config = {
        .mode = (i2s_mode_t) (I2S_MODE_TX | I2S_MODE_RX | I2S_MODE_MASTER),
        .sample_rate = 44100,
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
        .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
        .communication_format = I2S_COMM_FORMAT_STAND_I2S,
        .intr_alloc_flags = ESP_INTR_FLAG_LEVEL2 | ESP_INTR_FLAG_IRAM,
        .dma_buf_count = 2,
        .dma_buf_len = 128,
        .use_apll = true,
        .tx_desc_auto_clear = true,
    };
    int ret = i2s_driver_install(port, &i2s_config, 0, NULL);
    i2s_pin_config_t i2s_pin_cfg = {
        .mck_io_num = TEST_BOARD_I2S_MCK_PIN,
        .bck_io_num = TEST_BOARD_I2S_BCK_PIN,
        .ws_io_num = TEST_BOARD_I2S_DATA_WS_PIN,
        .data_out_num = TEST_BOARD_I2S_DATA_OUT_PIN,
        .data_in_num = TEST_BOARD_I2S_DATA_IN_PIN,
    };
    i2s_set_pin(port, &i2s_pin_cfg);
#endif
    return ret;
}

void app_main(void)
{

     // Need install driver (i2c and i2s) firstly
    int ret = ut_i2c_init(0);
    if(ret == ESP_OK)  printf("ut_i2c_init success.\n");
    else printf("ut_i2c_init failed.\n");

    ret = ut_i2s_init(0);
    if(ret == ESP_OK)  printf("ut_i2s_init success.\n");
    else printf("ut_i2s_init failed.\n");

    // Do initialize of related interface: data_if, ctrl_if and gpio_if
    audio_codec_i2s_cfg_t i2s_cfg = {
    #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
            .rx_handle = i2s_keep[0]->rx_handle,
            .tx_handle = i2s_keep[0]->tx_handle,
    #endif
        };
        const audio_codec_data_if_t *data_if = audio_codec_new_i2s_data(&i2s_cfg);
    TEST_ASSERT_NOT_NULL(data_if);

    audio_codec_i2c_cfg_t i2c_cfg = {.addr = ES8311_CODEC_DEFAULT_ADDR};

    #ifdef USE_IDF_I2C_MASTER
    i2c_cfg.bus_handle = i2c_bus_handle;
    #endif
    const audio_codec_ctrl_if_t *out_ctrl_if = audio_codec_new_i2c_ctrl(&i2c_cfg);
    TEST_ASSERT_NOT_NULL(out_ctrl_if);

    // i2c_cfg.addr = ES7210_CODEC_DEFAULT_ADDR;
    // const audio_codec_ctrl_if_t *in_ctrl_if = audio_codec_new_i2c_ctrl(&i2c_cfg);
    // TEST_ASSERT_NOT_NULL(in_ctrl_if);

    const audio_codec_gpio_if_t *gpio_if = audio_codec_new_gpio();
    TEST_ASSERT_NOT_NULL(gpio_if);

     // New output codec interface
    es8311_codec_cfg_t es8311_cfg = {
        .codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH,
        .ctrl_if = out_ctrl_if,
        .gpio_if = gpio_if,
        .pa_pin = GPIO_NUM_13,
        .use_mclk = true,
    };
    const audio_codec_if_t *out_codec_if = es8311_codec_new(&es8311_cfg);
    TEST_ASSERT_NOT_NULL(out_codec_if);

    // New output codec device
    esp_codec_dev_cfg_t dev_cfg = {
        .codec_if = out_codec_if,
        .data_if = data_if,
        .dev_type = ESP_CODEC_DEV_TYPE_IN_OUT,
    };
    esp_codec_dev_handle_t codec_dev = esp_codec_dev_new(&dev_cfg);
    TEST_ASSERT_NOT_NULL(codec_dev);
    
     // New input codec device
    // dev_cfg.codec_if = in_codec_if;
    // dev_cfg.dev_type = ESP_CODEC_DEV_TYPE_IN;
    // esp_codec_dev_handle_t record_dev = esp_codec_dev_new(&dev_cfg);
    // TEST_ASSERT_NOT_NULL(record_dev);

    ret = esp_codec_dev_set_out_vol(codec_dev, 80.0);
    TEST_ESP_OK(ret);
    // ret = esp_codec_dev_set_in_gain(record_dev, 30.0);
    // TEST_ESP_OK(ret);

    esp_codec_dev_sample_info_t fs = {
        .sample_rate = 48000,
        .channel = 2,
        .bits_per_sample = 16,
    };
    ret = esp_codec_dev_open(codec_dev, &fs);
    TEST_ESP_OK(ret);

   
    uint8_t data[256];
   
    printf("录制.\n");
    esp_codec_dev_set_in_gain(codec_dev, 30.0);
    esp_codec_dev_read(codec_dev, data, sizeof(data));
    printf("播放.\n");
    esp_codec_dev_write(codec_dev, data, sizeof(data));
    printf("结束.\n");


    
}

4.解决思路

感觉不能卡在一个硬件上了,多准备几个硬件试试,在网上找到了两个别人的PCB扩展板
es8311 - 立创开源硬件平台ES8311音频编解码芯片icon-default.png?t=O83Ahttps://oshwhub.com/Karmurphy/es8311

ES8311单声道I2S数字音频功放板 - 硬创社便宜的音频播放方案,电路全国产芯片。icon-default.png?t=O83Ahttps://x.jlc.com/platform/detail/599a993831d94f72a79ec35d067bad2d好东西值得被大家看到

简介: 便宜的音频播放方案,电路全国产芯片。
1.产品简介
一款便宜的高音质的单声道音频播放功能板板。



2.应用场景
低成本高音质音频开发,MP3等。



3.产品概述
使用低功耗低纹波的LDO给ES8311供电保证电源干扰最小
功放芯片通过排针选择使用LDO供电或者外部5V供电
一个3.5mm耳机接口,单声道,预留耳机插入检测
预留麦克风接口
预留功放芯片使能控制口
PCB四角有安装孔位Φ2.2mm
推荐使用8Ω的1.7W内喇叭,4Ω的声音小


4.产品参数
1.功能板输入电压:4V-5V

2.功能板输入电流:平均值120mA,最大值为900mA

3.音频芯片为ES8311,工作电压1.8-3.3V,功耗14mW

4.功放芯片为NS4150,工作电压3.0-5.25V,最大3W输出功率

5.电源芯片为ME6210A33M3G,输入耐压18V,输出电压3.3V,输出最大电流500mA

6.供电接口为2.54排针,通讯接口为2.54排针,喇叭接口为2.54排针,3.5mm耳机接口为PJ-342

7.PCB尺寸:51.7*34.1mm, 两层PCB设计。



5.使用说明
与ESP32 WROOM开发板连接

板子 ------------ ESP32

I2C_SDA -- GPIO18

I2C_SCK -- GPIO23

I2S_SCLK -- GPIO22

I2S_LRCK -- GPIO21

I2S_DSDIN -- GPIO17

VCC_IN -- VIN

GND -- GND

ES8311通过可选10K电阻选择I2C地址(默认拉低)

NS4150通过可选10K电阻选择启动或关闭(默认拉高)

功放电源选择建议5V

四角安装孔径Φ2.2mm

我这次直接在嘉立创上下单,并且ES8311让官方贴片,使用Esp32c3的开发板连接,就不信了。

有的东西是扩展库,我没让立创贴片,比如NS4150我自己贴。

另外看到这个作者用arduino写的蓝牙音箱,好家伙,只有短短几行,就可以实现,心态崩了。

#include <Arduino.h>
#include <btMusicBox.h>
#include <WiFi.h>
// 设置音频设备的名称
btMusicBox audio = btMusicBox("esp001");
String command;
#define I2C_SDA   18
#define I2C_SCL   23
#define I2S_SCLK  22  
#define I2S_DSDIN 17
#define I2S_LRCK  21
void setup()
{
  WiFi.mode(WIFI_OFF);

  Serial.begin(115200);
  Wire.end();
  Wire.begin(I2C_SDA, I2C_SCL); //SDA SCL
  Audio_codeC(ES8311);
  audio.begin();
  audio.I2S(I2S_SCLK, I2S_DSDIN, I2S_LRCK);
  audio.volume(1.0);      // 音量
  audio.reconnect();      // 重新连接到上次连接的设备
  //music.compress(thresh, attack, release, ratio, width, gain);

  Serial.printf("蓝牙示例开始...\n");
}
void loop()
{

}

但是俺的目的是理解单片机底层程序,比如i2c,i2s这些都是我这种做上位机没有接触过的,所以还是要学学ESP-IDF,不眼馋Arduino了。


http://www.kler.cn/a/540283.html

相关文章:

  • C++20新特性
  • 502 Bad Gateway 错误详解:从表现推测原因,逐步排查直至解决
  • 在离线的服务器上部署Python的安装库
  • java项目之金华学校社团管理系统源码(ssm+mysql)
  • 如何通过PHP接入DeepSeek的API
  • android手机安装deepseek-r1:1.5b
  • Django开发入门 – 2.Django的Web应用项目架构
  • flink JobGraph解析
  • leetcode刷题-动态规划04
  • 机器学习:学习记录(二)
  • Kotlin实战经验:将接口回调转换成suspend挂起函数
  • Bigemap Pro如何裁剪矢量数据
  • Ollama系列---【ollama使用gpu运行大模型】
  • 蓝耘智算平台部署deepseek-助力深度学习
  • webpack配置之---output.clean
  • AWS vs Azure vs 阿里云:出海企业全球扩张的技术选型指南(2024深度对比)
  • 如何使用 Redux 中间件?
  • 小白零基础如何搭建CNN
  • c# http
  • 1.1 单元测试核心原则
  • jenkins手动安装插件
  • 深度学习框架PyTorch
  • Python----PyQt开发(PyQt高级:组件大小,界面位置,按钮,文本显示,文本输入,字体大小)
  • Spring Boot + MyBatis Field ‘xxx‘ doesn‘t have a default value 问题排查与解决
  • 鸿蒙NEXT开发-发布三方库
  • CEF132 编译指南 MacOS 篇 - 启程:认识 CEF (一)