(一)创建音频文件,生成.bin文件

① 登录唯创知音官网:https://wt588f.waytronic.com:8443/
② 点击语音制作->点击WT588F->点击新增项目
在这里插入图片描述
③ 版本号:1(任意取);语音工程编号:AA(任意取);芯片类型:WT588E02B-8S;点击就下一步。
在这里插入图片描述
④ 点击增加TTS(可以在线生成自己需要的语音内容)在这里插入图片描述
⑤ 在输入文本中输入需要生成的语音内容,比如下图中,需要生成两条语音内容,那么在输入完成第一句话的时候,需要点击右上角的“插入行”,然后继续输入第二行的内容。最后点击批量添加既可。
在这里插入图片描述
⑥ 点击保存,然后点击地址列表
在这里插入图片描述
⑦ 下图中框选的是给生成的音频添加地址。在这里我们生成了两段音频,那么需要使用两个地址(到时候播放语音的时候,就是通过这个地址来实现的)
在这里插入图片描述
⑧ 先点击1,再点击2,然后再点击需要把哪个音频添加到地址为0000上。添加第二段音频,就点击地址为0001,然后继续把相应音频添加上去即可
在这里插入图片描述
在这里插入图片描述
⑨ 最后,先点击保存,然后点击合成.Bin文件即可,这样就得到了.bin的音频文件。
在这里插入图片描述

(二)构建SPI相关函数

  因为WT588E02B-8S是通过SPI来更新以及播放音频文件的,所以需要构建SPI相关的函数。

#include "bsp_wt558e02b.h"

uint16_t send_sum = 0;      	// 发送的校验和
uint16_t receive_sum = 0;   	// 接收的校验和
uint8_t data_buffer[512];  		// 存放.bin或T3Z文件内容的
uint8_t pack_len = 0;       	// .bin或T3Z文件大小(单位:512字节)

/******************************************** 以下为WT558902B-8S的代码 ********************************************/
void wt558_spi_init(void)
{
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOB);
    
    /* SCL */ 
    gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_3|GPIO_PIN_5);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3|GPIO_PIN_5);
    
    /* MISO */ 
    gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_4);
    
    /* SPI0_CS */
    gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_15);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_15);
    CS_HIGH;
}

void spi_wt588e_command(uint8_t ddata, uint8_t delay_cnt)
{
    uint8_t s_data = 0, j;
    uint8_t b_data = 0;
    s_data = ddata;
    b_data = s_data & 0X80;
    for(j = 0; j < 8; j++)
    {
        if(b_data){
            MOSI_HIGH;
        }else{
            MOSI_LOW;
        }
        SCL_HIGH; //时钟线拉高
        delay_us(delay_cnt);
        SCL_LOW; //时钟线拉低
        delay_us(delay_cnt);
        s_data = s_data << 1;
        b_data = s_data & 0X80;
    }
}

uint8_t spi_wt588e_byte(uint8_t delay_cnt)
{
    uint8_t r_data, j;
    MOSI_LOW;
    for(j = 0; j < 8; j++)
    {
        SCL_HIGH;            //时钟线拉高
        delay_us(delay_cnt);
        SCL_LOW;             //时钟线拉低
        r_data = r_data << 1;
        if(SPI_MISO == 1)           //接收一位数据
        {
            r_data = r_data | 0x01;
        }
        else
        {
            r_data = r_data & 0xFE;
        }
        delay_us(delay_cnt);
    }
    return r_data;
}

/* 语音芯片播放指令 */
void wt558_play(uint8_t ddata)
{
    SCL_LOW;        // 时钟线拉低
    CS_LOW;      // CS拉低
    delay_1ms(5);
    spi_wt588e_command(0xf0, 100);
    spi_wt588e_command(ddata, 100);
    CS_HIGH;
}

/* 语音数据全部更换握手指令 */
void data_change_all_start(void)
{
    SCL_LOW;
    CS_LOW;
    delay_1ms(5);
    spi_wt588e_command(0xe1, 100);
    delay_us(20);
    spi_wt588e_command(0xff, 100);
    send_sum = 0x01e0;
    CS_HIGH;
}

/* 语音数据单个地址更换握手指令 */
void data_change_single_start(uint8_t addr)
{
    SCL_LOW;
    CS_LOW;
    delay_1ms(5);
    spi_wt588e_command(0xe0, 100);
    delay_us(20);
    spi_wt588e_command(addr, 100);
    send_sum = 0xe0 + addr;
    CS_HIGH;
}

/* 语音数据更换结束指令 */
void data_change_end(void)
{
    SCL_LOW;
    CS_LOW;
    delay_1ms(5);
    spi_wt588e_command(0xef, 20);
    CS_HIGH;
}   

/* 语音数据更换一个包的开始指令1:检验成功;0:失败 */
uint8_t data_change_pack_start(void)
{
    uint16_t sum_temp = 0;
    receive_sum = 0;
    SCL_LOW;
    CS_LOW;
    delay_1ms(5);
    spi_wt588e_command(0xDF, 20);
    delay_us(20);
    sum_temp = spi_wt588e_byte(20);
    receive_sum = sum_temp;
    delay_us(20);
    sum_temp = spi_wt588e_byte(20);
    sum_temp = sum_temp<<8;
    receive_sum = receive_sum + sum_temp;
    CS_HIGH;
    if(send_sum == receive_sum){
        return 1;
    }else{
        return 0;
    }
}

/* 语音数据发送一个包 */
void data_change_pack_send(uint8_t *data_buf, uint16_t data_len)
{
    uint16_t sum_temp = 0;
    uint16_t j;
    send_sum = 0;
    CS_LOW;
    for(j=0;j<data_len;j++)
    {
        delay_us(20);
        spi_wt588e_command(*(data_buf+j), 10);
        sum_temp = *(data_buf+j);
        j++;
        delay_us(20);
        spi_wt588e_command(*(data_buf+j), 10);
        sum_temp = sum_temp + (*(data_buf+j)<<8);
        send_sum = send_sum + sum_temp;
    }
    CS_HIGH;
}

/* 语音数据全部更换1:更换成功;0:更换失败 */
uint8_t data_modify_change(void)
{
    uint8_t i = 0;
    uint16_t j = 0;
    data_change_all_start();
    delay_1ms(30);
    for(i=0;i<pack_len;i++)
    {
        delay_1ms(16);
        for(j = 0;j < 512;j++){
            data_buffer[j] = *(uint8_t *)((DOWNLOAD_START_PAGE*1024 + 0x08000000) + (j) + i*512);
        } 
        if(data_change_pack_start()==1){
            delay_1ms(1);
            data_change_pack_send(data_buffer,512);
        }else{
            return 0;
        }
    }
    data_change_end();
    return 1;
}

(三).bin文件烧录进入单片机内部flash中

  通过某个软件,把.bin文件下载到单片机的内部flash中,本文使用的单片机是GD23E230,使用的工具是j-link,使用的软件是j-flash来把.bin文件烧录到单片机的内部flash中。烧录的起始地址为:0x08006000(前24K字节用来存放Bootloader,后40K字节用来存放烧录的.bin文件)。

① 使用j-flash需要注意的细节就是导入.bin文件的时候,烧录的起始地址应该设置为:0x08006000。
在这里插入图片描述
② 烧录的时候,只需要点击Production Programming即可。
在这里插入图片描述

(四)单片机内部flash音频文件下载到WT588E02B-8S芯片中

  把已经烧录好的内部flash的.bin文件下载到WT588E02B-8S芯片中。只需要给pack_len变量赋值,以及调用data_modify_change()函数即可。
在这里插入图片描述

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐