LOADING

加载过慢请开启缓存 浏览器默认开启

毕业设计 (3) - 完成 WS63 的 ES8311 驱动移植和 MPU6050,实现音频播放和运动数据接收

踩坑:

 
模块的DI连接mcu的DO,DOUT连接模块的DI
又因为奇怪的原因浪费三四天时间

代码:

es8311音频播放代码

/*使用本案例前先把sio_porting.h和sio_porting.c中的FREQ_OF_NEED改成16*/
#include "i2s.h"
#include "watchdog.h"
#include "hal_sio.h"
#include "hal_dma.h"
#include "soc_osal.h"
#include "app_init.h"
#include "converted_audio_data.h"
#include "common_def.h"
#include "osal_debug.h"
#include "cmsis_os2.h"
#include "pinctrl.h"
#include "i2c.h"

#define I2S_DIV_NUMBER 16
#define I2S_CHANNEL_NUMBER 2
#define I2S_TX_INT_THRESHOLD 7
#define I2S_RX_INT_THRESHOLD 1
#define I2S_DMA_SRC_WIDTH 2
#define I2S_DMA_DEST_WIDTH 2
#define I2S_DMA_BURST_LENGTH 0
#define I2S_DMA_TRANS_STEP 2

#define I2S_TASK_PRIO 24
#define I2S_TASK_STACK_SIZE 0xc00

extern const int16_t my_converted_audio[];
#define MY_AUDIO_SAMPLES_LEN 56842
int16_t my_txdata[256] = {0};

#define I2S_SAMPLE_DELAY_MS 1000

/* ES8311 I2C配置 */
#define ES8311_I2C_BUS 1           /* I2C总线号 */
#define ES8311_I2C_ADDR 0x18       /* ES8311的7位I2C地址 */
#define ES8311_I2C_BAUDRATE 400000 /* I2C波特率 400kHz */

#define AUDIO_PLAY_BUF_SIZE 4096

#define ES8311_RESET_REG00 0x00 /* reset digital,csm,clock manager etc. */

#define ES8311_CLK_MANAGER_REG01 0x01 /* select clk src for mclk, enable clock for codec */
#define ES8311_CLK_MANAGER_REG02 0x02 /* clk divider and clk multiplier */
#define ES8311_CLK_MANAGER_REG03 0x03 /* adc fsmode and osr  */
#define ES8311_CLK_MANAGER_REG04 0x04 /* dac osr */
#define ES8311_CLK_MANAGER_REG05 0x05 /* clk divier for adc and dac */
#define ES8311_CLK_MANAGER_REG06 0x06 /* bclk inverter and divider */
#define ES8311_CLK_MANAGER_REG07 0x07 /* tri-state, lrck divider */
#define ES8311_CLK_MANAGER_REG08 0x08 /* lrck divider */
#define ES8311_SDPIN_REG09 0x09       /* dac serial digital port */
#define ES8311_SDPOUT_REG0A 0x0A      /* adc serial digital port */
#define ES8311_SYSTEM_REG0B 0x0B      /* system */
#define ES8311_SYSTEM_REG0C 0x0C      /* system */
#define ES8311_SYSTEM_REG0D 0x0D      /* system, power up/down */
#define ES8311_SYSTEM_REG0E 0x0E      /* system, power up/down */
#define ES8311_SYSTEM_REG0F 0x0F      /* system, low power */
#define ES8311_SYSTEM_REG10 0x10      /* system */
#define ES8311_SYSTEM_REG11 0x11      /* system */
#define ES8311_SYSTEM_REG12 0x12      /* system, Enable DAC */
#define ES8311_SYSTEM_REG13 0x13      /* system */
#define ES8311_SYSTEM_REG14 0x14      /* system, select DMIC, select analog pga gain */
#define ES8311_ADC_REG15 0x15         /* ADC, adc ramp rate, dmic sense */
#define ES8311_ADC_REG16 0x16         /* ADC */
#define ES8311_ADC_REG17 0x17         /* ADC, volume */
#define ES8311_ADC_REG18 0x18         /* ADC, alc enable and winsize */
#define ES8311_ADC_REG19 0x19         /* ADC, alc maxlevel */
#define ES8311_ADC_REG1A 0x1A         /* ADC, alc automute */
#define ES8311_ADC_REG1B 0x1B         /* ADC, alc automute, adc hpf s1 */
#define ES8311_ADC_REG1C 0x1C         /* ADC, equalizer, hpf s2 */
#define ES8311_DAC_REG31 0x31         /* DAC, mute */
#define ES8311_DAC_REG32 0x32         /* DAC, volume */
#define ES8311_DAC_REG33 0x33         /* DAC, offset */
#define ES8311_DAC_REG34 0x34         /* DAC, drc enable, drc winsize */
#define ES8311_DAC_REG35 0x35         /* DAC, drc maxlevel, minilevel */
#define ES8311_DAC_REG37 0x37         /* DAC, ramprate */
#define ES8311_GPIO_REG44 0x44        /* GPIO, dac2adc for test */
#define ES8311_GP_REG45 0x45          /* GP CONTROL */
#define ES8311_CHD1_REGFD 0xFD        /* CHIP ID1 */
#define ES8311_CHD2_REGFE 0xFE        /* CHIP ID2 */
#define ES8311_CHVER_REGFF 0xFF       /* VERSION */

#define ES8311_MAX_REGISTER 0xFF

#define ES8311_PDN_DAC_BIT (1 << 1)

#define CODEC_DEVICE_ADDR 0x30 /* 0011 00x */

typedef enum {
    HI_CODEC_SAMPLE_RATE_8K = 8,
    HI_CODEC_SAMPLE_RATE_16K = 16,
    HI_CODEC_SAMPLE_RATE_32K = 32,
    HI_CODEC_SAMPLE_RATE_48K = 48,
} hi_codec_sample_rate;

typedef enum {
    HI_CODEC_RESOLUTION_16BIT = 16,
    HI_CODEC_RESOLUTION_24BIT = 24,
} hi_codec_resolution;

typedef struct {
    hi_codec_sample_rate sample_rate;
    hi_codec_resolution resolution;
} hi_codec_attribute;

/**
 * @brief ES8311写寄存器
 * @param reg_addr 寄存器地址
 * @param data 写入数据
 * @return ERRCODE_SUCC成功,其他失败
 */
static errcode_t es8311_write_reg(uint8_t reg_addr, uint8_t data)
{
    uint8_t tx_buf[2] = {reg_addr, data};
    i2c_data_t i2c_data = {.send_buf = tx_buf, .send_len = 2, .receive_buf = NULL, .receive_len = 0};

    return uapi_i2c_master_write(ES8311_I2C_BUS, ES8311_I2C_ADDR, &i2c_data);
}

/**
 * @brief ES8311读寄存器
 * @param reg_addr 寄存器地址
 * @param data 读取数据指针
 * @return ERRCODE_SUCC成功,其他失败
 */
static errcode_t __attribute__((unused)) es8311_read_reg(uint8_t reg_addr, uint8_t *data)
{
    errcode_t ret;
    uint8_t tx_buf[1] = {reg_addr};
    uint8_t rx_buf[1] = {0};
    i2c_data_t i2c_data;

    /* 先写寄存器地址 */
    i2c_data.send_buf = tx_buf;
    i2c_data.send_len = 1;
    i2c_data.receive_buf = NULL;
    i2c_data.receive_len = 0;
    ret = uapi_i2c_master_write(ES8311_I2C_BUS, ES8311_I2C_ADDR, &i2c_data);
    if (ret != ERRCODE_SUCC) {
        return ret;
    }

    /* 再读寄存器数据 */
    osal_msleep(1);
    i2c_data.send_buf = NULL;
    i2c_data.send_len = 0;
    i2c_data.receive_buf = rx_buf;
    i2c_data.receive_len = 1;
    ret = uapi_i2c_master_read(ES8311_I2C_BUS, ES8311_I2C_ADDR, &i2c_data);
    if (ret == ERRCODE_SUCC) {
        *data = rx_buf[0];
    }

    return ret;
}

__attribute__((unused)) static uint32_t codec_set_gain(void)
{
    uint32_t ret = ERRCODE_SUCC;
    ret |= es8311_write_reg(ES8311_SYSTEM_REG0E, 0x02);
    ret |= es8311_write_reg(ES8311_SYSTEM_REG0F, 0x44);
    ret |= es8311_write_reg(ES8311_ADC_REG15, 0x40);
    ret |= es8311_write_reg(ES8311_ADC_REG1B, 0x0A);
    ret |= es8311_write_reg(ES8311_ADC_REG1C, 0x6A);
    ret |= es8311_write_reg(ES8311_ADC_REG17, 0xBF);
    ret |= es8311_write_reg(ES8311_DAC_REG37, 0x48);
    ret |= es8311_write_reg(ES8311_DAC_REG32, 0x84);
    ret |= es8311_write_reg(ES8311_ADC_REG16, 0x22);
    ret |= es8311_write_reg(ES8311_ADC_REG17, 0xDF);
    ret |= es8311_write_reg(ES8311_ADC_REG18, 0x87);
    ret |= es8311_write_reg(ES8311_ADC_REG19, 0xFB);
    ret |= es8311_write_reg(ES8311_ADC_REG1A, 0x03);
    ret |= es8311_write_reg(ES8311_ADC_REG1B, 0xEA);

    return ret;
}

/**
 * @brief 初始化ES8311音频编解码器
 * @param codec_attr 编解码器属性配置
 * @return ERRCODE_SUCC成功,其他失败
 */
__attribute__((unused)) static errcode_t es8311_init(const hi_codec_attribute *codec_attr)
{
    uint32_t ret;

    osal_printk("========== ES8311 Init Start ==========\r\n");

    if (codec_attr == NULL) {
        osal_printk("codec_attr is NULL!\r\n");
        return ERRCODE_FAIL;
    }

    /* 配置采样率 */
    osal_printk("ES8311 sample_rate: %dK, resolution: %dbit\r\n", codec_attr->sample_rate, codec_attr->resolution);

    ret = es8311_write_reg(ES8311_GPIO_REG44, 0x08);
    osal_msleep(5);

    ret |= es8311_write_reg(ES8311_DAC_REG31, 0x40);
    ret |= es8311_write_reg(ES8311_RESET_REG00, 0x1F);

    ret |= es8311_write_reg(ES8311_GP_REG45, 0x00);
    ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, 0x30);
    ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, 0x10);

    if (codec_attr->sample_rate == HI_CODEC_SAMPLE_RATE_8K) {
        ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, 0xA0);
    } else if (codec_attr->sample_rate == HI_CODEC_SAMPLE_RATE_16K) {
        ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, 0x40);
    } else if (codec_attr->sample_rate == HI_CODEC_SAMPLE_RATE_32K) {
        ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, 0x48);
    } else if (codec_attr->sample_rate == HI_CODEC_SAMPLE_RATE_48K) {
        ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, 0x00);
    }

    if ((codec_attr->resolution == HI_CODEC_RESOLUTION_16BIT)) {
        ret |= es8311_write_reg(ES8311_SDPIN_REG09, 0x0C);
        ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, 0x0C);
    } else {
        ret |= es8311_write_reg(ES8311_SDPIN_REG09, 0x00);
        ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, 0x00);
    }

    return ERRCODE_SUCC;
}

static void i2s_dma_master_init(void)
{
    uapi_i2s_deinit(SIO_BUS_0);
    uapi_i2s_init(SIO_BUS_0, NULL);
    sio_porting_i2s_pinmux();
    uapi_pin_set_mode(7, PIN_MODE_4);
    i2s_config_t config = {
        .drive_mode = MASTER,
        .transfer_mode = STD_MODE,
        .data_width = SIXTEEN_BIT,
        .channels_num = TWO_CH,
        .timing = NONE_TIMING_MODE,
        .clk_edge = RISING_EDGE,
        .div_number = I2S_DIV_NUMBER,
        .number_of_channels = I2S_CHANNEL_NUMBER,
    };
    i2s_dma_attr_t attr = {
        .tx_dma_enable = 1,
        .tx_int_threshold = I2S_TX_INT_THRESHOLD,
        .rx_dma_enable = 0,
        .rx_int_threshold = I2S_RX_INT_THRESHOLD,
    };
    uapi_i2s_set_config(SIO_BUS_0, &config);
    uapi_i2s_dma_config(SIO_BUS_0, &attr);
}

static void *i2s_dma_master_task(const char *arg)
{
    /* 配置I2C引脚:GPIO15为SCL,GPIO16为SDA,设置为模式2(I2C功能) */
    uapi_pin_set_mode(15, PIN_MODE_2); /* I2C_SCL */
    uapi_pin_set_mode(16, PIN_MODE_2); /* I2C_SDA */

    /* 初始化I2C主机 */
    uapi_i2c_master_init(ES8311_I2C_BUS, ES8311_I2C_BAUDRATE, 0);

    /* 配置编解码器属性 */
    __attribute__((unused)) hi_codec_attribute codec_attr = {
        .sample_rate = HI_CODEC_SAMPLE_RATE_16K, .resolution = HI_CODEC_RESOLUTION_16BIT, /* 16位分辨率 */
    };

    /* 初始化ES8311 */
    // es8311_init(&codec_attr);

    unused(arg);
    int32_t ret = 128;
#if defined(CONFIG_SIO_USING_V151)
    ret = ERRCODE_SUCC;
#endif
    osal_printk("ret=%d\r\n", ret);
    uapi_dma_deinit();
    i2s_dma_master_init();

    /* DMA init. */
    uapi_dma_init();
    uapi_dma_open();
    i2s_dma_config_t dma_cfg = {
        .src_width = I2S_DMA_SRC_WIDTH,
        .dest_width = I2S_DMA_DEST_WIDTH,
        .burst_length = I2S_DMA_BURST_LENGTH,
        .priority = 0,
    };
    osal_printk("playing threading start.\r\n");

    int p = 0;
    while (1) {
        uapi_watchdog_kick();

        while (1) {
            for (int i = 0; i < 64; i++) {
                for (int j = 0; j < 4; j++) {
                    my_txdata[i * 4 + j] = my_converted_audio[p + i];
                }
            }

            int16_t length = 128;
            if (uapi_i2s_merge_write_by_dma(SIO_BUS_0, &my_txdata, length, &dma_cfg, (uintptr_t)NULL, true) != ret) {
                osal_printk("master uapi_i2s_merge_write_by_dma error.\r\n");
            }

            p += 64; // 更新 p 以指向下一个数据块
            if (p > MY_AUDIO_SAMPLES_LEN - 64) {
                osal_printk("master uapi_i2s_merge_write_by_dma end.\r\n");
                p = 0; // 重置 p 以循环播放音频数据
                break; // 跳出循环,等待下一次播放
            }
        }
    }
    return NULL;
}

static void i2s_entry(void)
{
    osal_task *task_handle = NULL;
    osal_kthread_lock();
    task_handle =
        osal_kthread_create((osal_kthread_handler)i2s_dma_master_task, 0, "I2sDmaMasterTask", I2S_TASK_STACK_SIZE);
    if (task_handle != NULL) {
        osal_kthread_set_priority(task_handle, I2S_TASK_PRIO);
    }
    osal_kthread_unlock();
}

/* Run the i2s_entry. */
app_run(i2s_entry);

 
 
 
下一步准备开始数据采集打标签

问答