stm32的timer-trgo + DMA + DAC 播放WAV格式音乐

1、考虑到stm32F103的flash大小有限,所以音频数据存在spi-flash中,WAV文件有6段语音。合成在一起大概有1.3M(客户给的文件)。所以用Audition软件把WAV文件转换成8k采样频率和8位数据格式(PS:音质效果还可以),文件大小变为126k,spi-flash有4M字节, 完全可以存下。

2、考虑到CPU的效率问题,采用TIMER+DMA的方式输送音频数据,下面贴出DAC的配置,采用的是DAC的通道1,即对应的PA4引脚,下面贴出DAC配置代码。

    GPIO_InitTypeDef GPIO_InitStructure;
    DAC_InitTypeDef            DAC_InitStructure;
    uint8_t i;
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);
    
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4; //| GPIO_PIN_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    DAC_InitStructure.DAC_Trigger                      = DAC_Trigger_T5_TRGO;
    // 不生成波形
    DAC_InitStructure.DAC_WaveGeneration               = DAC_WaveGeneration_None;
    DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;   
    // 输出缓存开启
    DAC_InitStructure.DAC_OutputBuffer                 = DAC_OutputBuffer_Enable;
    DAC_Init(DAC_Channel_1, &DAC_InitStructure);
    // PA4
    DAC_DMACmd(DAC_Channel_1, ENABLE);
    DAC_SetChannel1Data(DAC_Align_8b_R, 0);  //8位右对齐数据格式设置DAC

值

说明: DAC触发信号配置为定时器5的TRGO触发, 开启DAC输出缓存功能,使DAC驱动增大。

3、下面是播放音乐的详细代码

/***************************************************************************************
函数名称: void play_music(uint8_t data)
函数功能: 播放音乐函数
输入参数: 第几段音乐
返 回 值: 无
***************************************************************************************/
void play_music(uint8_t data)
{
    uint32_t play_addr, play_len, len;
    uint32_t file_addr, file_len;

    //==================================================================================
    //==================================================================================
    file_addr = music_file_offset(data, &file_len, &play_len);
    if (file_len == 0)
        return;
   
    play_addr = file_addr + sizeof(wav_typedef);
    //==================================================================================
    // dma-dac输出音乐数据
    //==================================================================================
    while (play_len != 0)
    {
        //==================================================================================
        // 播放当前缓存,
        //==================================================================================
        if (play_len > DAC_DMA_NUM)
            len = DAC_DMA_NUM;
        else if (play_len > 0)
            len = play_len;
        else
            break;
        
        music_flash_read(play_addr, dac_buf1, len);
        dac_dma_send(dac_buf1, len);
        play_len -= len;
        play_addr += len;
        //==================================================================================
        //  初始化下一缓存数据
        //==================================================================================
        if (play_len > DAC_DMA_NUM)
            len = DAC_DMA_NUM;
        else if (play_len > 0)
            len = play_len;
        else
            break;
        
        music_flash_read(play_addr, dac_buf2, len);
        dac_dma_send(dac_buf2, len);
        play_len -= len;
        play_addr += len;
    }
}

具体细节, 比如每播放一段语音后开始或者结束时都有一点杂音,这些问题已经解决,需要完整源代码的可以私聊我哦,微信电话:18666267395