打印
[STM32H7]

【STM32H745I-DISCO试用】11、播放MP3

[复制链接]
26|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 sujingliang 于 2025-2-11 19:41 编辑


为了实现播放MP3文件需要完成以下工作:
1、利用FATFS读取位于EMMC上的mp3文件,这些mp3文件可以将EMMC模拟成U盘方式拷贝到EMMC上。
2、利用ST官方提供的mp3解码软件包实现mp3文件解码:
从st.com上下载X-CUBE-AUDIO开发包


将其中的SpiritDSP_MP3_Dec加入自己的工程。

3、利用SAI驱动EM8994播放音乐。

一、定义一些常量
/* Audio PDM FS frequency = 128KHz = 8 * 16KHz = 8 * FS_Freq */
#define AUDIO_PDM_GET_FS_FREQUENCY(FS)  (FS * 8)

#define AUDIO_FREQUENCY       SAI_AUDIO_FREQUENCY_16K
#define AUDIO_CHANNEL_NUMBER  2U
#define AUDIO_BUFFER_SIZE     256U
#define AUDIO_PCM_CHUNK_SIZE  32U


//static FILINFO file_information;
static FIL file_object;
__attribute__((aligned(4))) DWORD clmt[2400];                                                                                                                                                                                                 // Cluster link map table buffer
__attribute__((aligned(4))) short audio_output_buffer[8192]  __attribute__((section(".bss.ARM.__at_0xD0400000")));
audio_output_buffer是音频缓冲,位于0xD0400000

二、WM8994初始化

static int32_t WM8994_Probe(void)
{
  int32_t ret = BSP_ERROR_NONE;
  WM8994_IO_t              IOCtx;
  static WM8994_Object_t   WM8994Obj;
  uint32_t id;

  /* Configure the audio driver */
  IOCtx.Address     = AUDIO_I2C_ADDRESS;
  IOCtx.Init        = BSP_I2C4_Init;
  IOCtx.DeInit      = BSP_I2C4_DeInit;
  IOCtx.ReadReg     = BSP_I2C4_ReadReg16;
  IOCtx.WriteReg    = BSP_I2C4_WriteReg16;
  IOCtx.GetTick     = BSP_GetTick;

  if(WM8994_RegisterBusIO (&WM8994Obj, &IOCtx) != WM8994_OK)
  {
    ret = BSP_ERROR_BUS_FAILURE;
  }
  else
  {
    /* Reset the codec */
    if(WM8994_Reset(&WM8994Obj) != WM8994_OK)
    {
      ret = BSP_ERROR_COMPONENT_FAILURE;
    }
    else if(WM8994_ReadID(&WM8994Obj, &id) != WM8994_OK)
    {
      ret = BSP_ERROR_COMPONENT_FAILURE;
    }
    else if(id != WM8994_ID)
    {
      ret = BSP_ERROR_UNKNOWN_COMPONENT;
    }
    else
    {
      Audio_Drv = (AUDIO_Drv_t *) &WM8994_Driver;
      Audio_CompObj = &WM8994Obj;
    }
  }
  return ret;
}


三、SAI初始化
static void Playback_Init(void)
{
  RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct;

  /* Configure PLLSAI1 prescalers */
  /* PLLSAI_VCO: VCO_512M
     SAI_CLK(first level) = PLLSAI_VCO/PLLSAIP = 512/125 = 4.096 Mhz */
  RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
  RCC_PeriphCLKInitStruct.Sai23ClockSelection = RCC_SAI2CLKSOURCE_PLL2;
  RCC_PeriphCLKInitStruct.PLL2.PLL2P = 125;
  RCC_PeriphCLKInitStruct.PLL2.PLL2Q = 1;
  RCC_PeriphCLKInitStruct.PLL2.PLL2R = 1;
  RCC_PeriphCLKInitStruct.PLL2.PLL2N = 512;
  RCC_PeriphCLKInitStruct.PLL2.PLL2FRACN = 0;
  RCC_PeriphCLKInitStruct.PLL2.PLL2M = 25;

  if(HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /* Configure PLLSAI4A prescalers */
  RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI4A;
  RCC_PeriphCLKInitStruct.Sai4AClockSelection = RCC_SAI4ACLKSOURCE_PLL2;
  if(HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /* SAI PCM Output init */
  __HAL_SAI_RESET_HANDLE_STATE(&haudio_out_sai);

  haudio_out_sai.Instance            = AUDIO_OUT_SAIx;
  haudio_out_sai.Init.AudioMode      = SAI_MODEMASTER_TX;
  haudio_out_sai.Init.Synchro        = SAI_ASYNCHRONOUS;
  haudio_out_sai.Init.OutputDrive    = SAI_OUTPUTDRIVE_ENABLE;
  haudio_out_sai.Init.NoDivider      = SAI_MASTERDIVIDER_ENABLE;
  haudio_out_sai.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_1QF;
  haudio_out_sai.Init.AudioFrequency = AUDIO_FREQUENCY;
  haudio_out_sai.Init.Protocol       = SAI_FREE_PROTOCOL;
  haudio_out_sai.Init.DataSize       = SAI_DATASIZE_16;
  haudio_out_sai.Init.FirstBit       = SAI_FIRSTBIT_MSB;
  haudio_out_sai.Init.ClockStrobing  = SAI_CLOCKSTROBING_FALLINGEDGE;

  haudio_out_sai.FrameInit.FrameLength       = 128;
  haudio_out_sai.FrameInit.ActiveFrameLength = 64;
  haudio_out_sai.FrameInit.FSDefinition      = SAI_FS_CHANNEL_IDENTIFICATION;
  haudio_out_sai.FrameInit.FSPolarity        = SAI_FS_ACTIVE_LOW;
  haudio_out_sai.FrameInit.FSOffset          = SAI_FS_BEFOREFIRSTBIT;

  haudio_out_sai.SlotInit.FirstBitOffset = 0;
  haudio_out_sai.SlotInit.SlotSize       = SAI_SLOTSIZE_DATASIZE;
  haudio_out_sai.SlotInit.SlotNumber     = 4;
  haudio_out_sai.SlotInit.SlotActive     = (SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_2);

  /* DeInit SAI PCM input */
  HAL_SAI_DeInit(&haudio_out_sai);

  /* Init SAI PCM input */
  if(HAL_OK != HAL_SAI_Init(&haudio_out_sai))
  {
    Error_Handler();
  }

  /* Enable SAI to generate clock used by audio driver */
  __HAL_SAI_ENABLE(&haudio_out_sai);
    WM8994_Probe();

  /* Init PDM Filters */
//  AUDIO_IN_PDMToPCM_Init(AUDIO_FREQUENCY, AUDIO_CHANNEL_NUMBER);
}
四、列出所有的mp3文件名
void list_mp3_files(const char *path)
{
    DIR dir;
    FILINFO fileInfo;


    // 挂载文件系统
    FRESULT res = f_mount(&MMCFatFs, (TCHAR const*)MMCPath, 0);
    if (res != FR_OK) {
        printf("Failed to mount filesystem: %d\n", res);
        return;
    }

    // 打开目录
    res = f_opendir(&dir, path);
    if (res != FR_OK) {
        printf("Failed to open directory: %d\n", res);
        f_mount(NULL, "", 0);  // 卸载文件系统
        return;
    }

    // 遍历目录
    while (1) {
        res = f_readdir(&dir, &fileInfo);
        if (res != FR_OK || fileInfo.fname[0] == 0) {
            break;  // 遍历完成或出错
        }

        // 检查是否为 MP3 文件
        if (!(fileInfo.fattrib & AM_DIR)) {  // 排除目录
            char *ext = strrchr(fileInfo.fname, '.');  // 获取文件扩展名
            if (ext && strcmp(ext, ".mp3") == 0) {    // 检查扩展名是否为 .mp3
                strncpy(mp3Files[mp3Count], fileInfo.fname, 255);  // 存储文件名
                mp3Count++;
                if (mp3Count >= 100) {
                    break;  // 达到最大存储数量
                }
            }
        }
    }

    // 关闭目录
    f_closedir(&dir);

    // 卸载文件系统
    f_mount(NULL, "", 0);

    // 打印所有 MP3 文件名
    for (int i = 0; i < mp3Count; i++) {
        printf("MP3 File: %s\n", mp3Files[i]);
    }
}
五、初始化MP3播放器
/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  初始化MP3播放器
        * @param  mp3_file: MP3文件的名字
        * @param  vol: 音量
        * @param  output_device: 0--耳机  1--喇叭
  * @retval 1:成功 0:失败
  */
unsigned char st_mp3_player_Init( char *mp3_file, unsigned char vol, unsigned char output_device )
{
        unsigned int read_num;
        unsigned int ID3_Length, temp1;
        unsigned char buf[4];
        uint32_t *AudioFreq_ptr;
        uwVolume = vol;
        
        memset( SongInfo.FileName, 0, 30 );
        
        /* Register the file system object to the FatFs module */
  if(f_mount(&MMCFatFs, (TCHAR const*)MMCPath, 0) != FR_OK)
  {
                printf("f_mount error\r\n");
                return 0;
  }
        
        if( f_open( &file_object, mp3_file, FA_OPEN_EXISTING | FA_READ ) != FR_OK )
        {
                printf("MP3 File Open Err!!!\r\n" );
                return 0;
        }
        
        /*        使能FATFS的快速读写功能        */
        if( f_lseek(&file_object, 4)!= FR_OK )
        {
                f_close( &file_object );
                printf("faftfs fast seek feature err!!!\r\n" );
                return 0;
        }
        
        file_object.cltbl = clmt;                                                               /* Enable fast seek feature (cltbl != NULL) */
  clmt[0] = 2400;                                                                                                                                                                                /* Set table size */
        
        if( f_lseek(&file_object, CREATE_LINKMAP) != FR_OK )                                                        /* Create CLMT */
        {
                f_close( &file_object );
                printf("faftfs fast seek feature err!!!\r\n" );
                return 0;
        }
        
        if( f_lseek(&file_object, 0)!= FR_OK )
        {
                f_close( &file_object );
                printf("faftfs fast seek feature err!!!\r\n" );
                return 0;
        }
        
        //计算文件大小
        SongInfo.FileSize = f_size( &file_object );
        memcpy( SongInfo.FileName, mp3_file, strlen( mp3_file) );
        
        //判断打开的文件是否是mp3文件
        if( f_read( &file_object, buf, 3, &read_num ) != FR_OK )
        {
                f_close( &file_object );
                return 0;
        }
        
        if( memcmp( buf, (unsigned char *)"ID3", 3 ) != 0 )
        {
                f_close( &file_object );
                printf("It is not mp3 file!!!\r\n" );
                return 0;
        }
        
        //开始计算ID3标签头大小
        f_lseek( &file_object, 6 );
        
        if( f_read( &file_object, buf, 4, &read_num ) != FR_OK )
        {
                f_close( &file_object );
//                printf("读取文件失败。\r\n" );
                return 0;
        }
        
        ID3_Length = (buf[0] & 0x7f) * 0x200000;                                                                                                                                                                        //计算ID3标签头的大小
        ID3_Length = ID3_Length + ( (buf[1] & 0x7f) * 0x400 );
        ID3_Length = ID3_Length + ( (buf[2] & 0x7f) * 0x80 );
        ID3_Length = ID3_Length + (buf[3] & 0x7f) + 10;
        
        //跳转到ID3标签结束位置,准备获取mp3文件信息
        f_lseek( &file_object, ID3_Length );
        SongInfo.file_ptr = ID3_Length;
        
        //初始化MP3解码器
        memset( &g_MP3Decoder, 0, sizeof( TSpiritMP3Decoder ) );
        SpiritMP3DecoderInit(        &g_MP3Decoder, // MP3 decoder object
                                                                                                RetrieveMP3Data, // Input callback function
                                                                                                NULL, // No post-process callback
                                                                                                NULL // Callback parameter
                                                                                        );
        
        //获取mp3文件信息
        while( 1 )
        {
                Audio_Delay_1ms( 3 );
               
                temp1 = SpiritMP3Decode(         &g_MP3Decoder,                                                     /* Decoder structure */
                                                                                                                        (short *)&audio_output_buffer[0],   /* [OUT] Output PCM buffer */
                                                                                                                        1152,                                                                                                 /* Number of samples to decode (1 sample = 32 bit = 2ch*16 bit) */
                                                                                                                        &MP3Info                                                    /* [OUT, opt] Optional informational structure */
                                                                                                         );        
                //到达文件末尾,没有获取mp3文件信息,退出                                                                                       
                if( temp1 < 1152 )
                {
                        f_close( &file_object );
                        printf("Get MP3 Info Err!!!\r\n");
                        return 0;
                }
               
                //获取到正确的MP3信息
                if( MP3Info.IsGoodStream == 1 && MP3Info.nSampleRateHz != 0 && MP3Info.nBitrateKbps != 0 )
                {
                        MPEGAudioFrameInfo.mSamplesPerFrame = MP3Info.nSamplesPerFrame;
                        MPEGAudioFrameInfo.mBitrate = MP3Info.nBitrateKbps * 1000;
                        SongInfo.Bitrate = MPEGAudioFrameInfo.mBitrate;
                        MPEGAudioFrameInfo.mChannelMode = MP3Info.nChannels;
                        MPEGAudioFrameInfo.mLayer = MP3Info.nLayer;
                        MPEGAudioFrameInfo.mSamplerate = MP3Info.nSampleRateHz;
                        //计算歌曲的播放时长
                        SongInfo.time = (SongInfo.FileSize - ID3_Length) * 8 / SongInfo.Bitrate;
                        
                        printf("\r\n");
                        printf( "mp3 SamplesPerFrame:%d\r\n", MPEGAudioFrameInfo.mSamplesPerFrame );
                        printf( "mp3 Bitrate:%d\r\n", MPEGAudioFrameInfo.mBitrate );
                        printf( "mp3 Samplerate:%d\r\n", MPEGAudioFrameInfo.mSamplerate );
                        printf( "mp3 ChannelMode:%d\r\n", MPEGAudioFrameInfo.mChannelMode );
                        printf( "mp3 Layer:%d\r\n", MPEGAudioFrameInfo.mLayer );
                        printf( "mp3 FileSize:%d\r\n", SongInfo.FileSize );
                        printf( "mp3 PlayTime:%d\r\n", SongInfo.time );
                        
                        Display_SongDescription();
                        break;
                }
        }
        
        
        //重新初始化MP3解码器,准备开始解码
        memset( &g_MP3Decoder, 0, sizeof( TSpiritMP3Decoder ) );
        SpiritMP3DecoderInit(        &g_MP3Decoder, // MP3 decoder object
                                                                                                RetrieveMP3Data, // Input callback function
                                                                                                NULL, // No post-process callback
                                                                                                NULL // Callback parameter
                                                                                        );
        
        //跳转到ID3标签头结束位置,从此位置开始解码
        f_lseek( &file_object, ID3_Length );
        SongInfo.file_ptr = ID3_Length;
        /*
        for(int i=0;i<sizeof(AudioFreq);i++)
        {
                if(abs((int)(AudioFreq[i]-MPEGAudioFrameInfo.mSamplerate))<100)
                {
                        AudioFreq_ptr=&AudioFreq[i];
                        break;
                }
        }
        */
        AudioFreq[0]=MPEGAudioFrameInfo.mSamplerate;
        AudioFreq_ptr=&AudioFreq[0];
        //AudioFreq_ptr = &AudioFreq[6]; /*96K*/
        
        AudioPlayInit->Device = AUDIO_OUT_DEVICE_HEADPHONE;
  AudioPlayInit->ChannelsNbr = 2;
  AudioPlayInit->SampleRate = *AudioFreq_ptr;
  AudioPlayInit->BitsPerSample = AUDIO_RESOLUTION_16B;
  AudioPlayInit->Volume = uwVolume;
        
        //配置WM8994的工作模式
        if( BSP_AUDIO_OUT_Init( 0, AudioPlayInit ) != 0 )
        {
                f_close( &file_object );
                printf("WM8994 Init Err!!!\r\n");
                return 0;
        }
        
        //if( output_device == 0 ) BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
        //else BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_13);

        return 1;
}
六、播放MP3函数
/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  播放MP3
        * @param  time: MP3文件开始播放的时间点(不超过MP3播放时间的最大值),单位:s
  * @retval 1:成功 0:失败
  */
unsigned char st_mp3play( unsigned short int time )
{
        signed int temp = 0;
        unsigned int nSamples = 0;
        unsigned int addr = 0;
        uint8_t index=mp3Current;
        
        SongInfo.state = OK;
        SongInfo.time_count = time;
        
        if( time >= (SongInfo.time-2) )
        {
                BSP_AUDIO_OUT_Stop(CODEC_PDWN_SW);
                f_close( &file_object );
                return 1;
        }
        
        //根据播放起始时间,计算文件指针起始位置
        addr = (time * SongInfo.Bitrate / 8 );
        if( addr == 0 )
        {
                if( f_lseek(&file_object, SongInfo.file_ptr ) != FR_OK )
                {
                        f_close( &file_object );               
                        BSP_AUDIO_OUT_Stop(CODEC_PDWN_SW);
                        return 0;
                }
        }
        else
        {
                addr += SongInfo.file_ptr;
                SongInfo.file_ptr = addr;
               
                if( f_lseek(&file_object, SongInfo.file_ptr) != FR_OK )
                {
                        f_close( &file_object );
                        BSP_AUDIO_OUT_Stop(CODEC_PDWN_SW);
                        return 0;
                }
        }
        

        /*        先解码两帧mp3音频数据,用于填充audio_output_buffer */
        temp = 0;
        while( temp < 2 )
        {
                nSamples = SpiritMP3Decode( &g_MP3Decoder,                                                                                             /* Decoder structure */
                                                                                                                                (short *)&audio_output_buffer[temp*MPEGAudioFrameInfo.mSamplesPerFrame*2],   /* [OUT] Output PCM buffer */
                                                                                                                                MPEGAudioFrameInfo.mSamplesPerFrame,          /* Number of samples to decode (1 sample = 32 bit = 2ch*16 bit) */
                                                                                                                                &MP3Info                                                                                            /* [OUT, opt] Optional informational structure */
                                                                                                                        );        
                                                                                                                                       
                printf("Samples:%d\r\n", nSamples);

                if( MP3Info.IsGoodStream == 1 )
                {
                        temp++;
                }
               
                /*        到达文件末尾,则退出        */
                if( nSamples < MPEGAudioFrameInfo.mSamplesPerFrame||index!= mp3Current)
                {
                        f_close( &file_object );
                        BSP_AUDIO_OUT_Stop(CODEC_PDWN_SW);
                        return 0;
                }
               
                Audio_Delay_1ms( 3 );
        }
        
        TxHalfCpltFlag = 0;
        TxCpltFlag = 0;
        TxBufNum = 0;
        AudioOutFlag = 0;
        Audio_ErrorFlag = 0;
        
        //开始播放
        BSP_AUDIO_OUT_Play( 0,(uint8_t*)audio_output_buffer, (MPEGAudioFrameInfo.mSamplesPerFrame*2*2*2) );
        AudioOutFlag = 1;
        while( 1 )
        {
                while( AudioOutFlag == 1 )
                {
                        //播放状态--暂停
                        if( SongInfo.state == Pause )
                        {
                                BSP_AUDIO_OUT_Pause(0);
                                
                                while( SongInfo.state == Pause )
                                {
                                        Audio_Delay_1ms( 10 );
                                }
                        }
                        //播放状态--恢复
                        else if( SongInfo.state == Resume )
                        {
                                BSP_AUDIO_OUT_Resume( 0 );
                                SongInfo.state = OK;
                        }
                        //播放状态--停止
                        else if( SongInfo.state == Stop )
                        {
                                BSP_AUDIO_OUT_Stop(CODEC_PDWN_SW);
                                f_close( &file_object );
               
                                SongInfo.state = OK;
                                return 1;
                        }
                        //播放状态--错误
                        else if( Audio_ErrorFlag == 1 )
                        {
                                BSP_AUDIO_OUT_Stop(CODEC_PDWN_SW);
                                f_close( &file_object );
                                return 0;
                        }
        
                        Audio_Delay_1ms( 3 );
                }
               
                //计算当前歌曲时间点
                SongInfo.time_count = SongInfo.file_ptr * 8 / SongInfo.Bitrate ;
                //printf("SongInfo.time_count:%d\r\n",SongInfo.time_count);
               
                //audio_output_buffer已通过DMA传输一半
                if( TxHalfCpltFlag == 1 )
                {
                        //解码MP3音频数据,用来填充audio_output_buffer
                        while( 1 )
                        {
                                nSamples = SpiritMP3Decode( &g_MP3Decoder,                                                                                             /* Decoder structure */
                                                                                                                                                (short *)&audio_output_buffer[0],                                           /* [OUT] Output PCM buffer */
                                                                                                                                                MPEGAudioFrameInfo.mSamplesPerFrame,          /* Number of samples to decode (1 sample = 32 bit = 2ch*16 bit) */
                                                                                                                                                &MP3Info                                                                                            /* [OUT, opt] Optional informational structure */
                                                                                                                                        );        
                                /*到达文件末尾, 则退出*/
                                if( nSamples < MPEGAudioFrameInfo.mSamplesPerFrame ||index!= mp3Current)
                                {
                                        BSP_AUDIO_OUT_Stop(CODEC_PDWN_SW);
                                        f_close( &file_object );
                                        return 1;
                                }
                                
                                if( !( !MP3Info.IsGoodStream || (MP3Info.nBitrateKbps == 0) || (MP3Info.nSampleRateHz == 0) ) )
                                {
                                        break;
                                }
                        }
                }
               
                //audio_output_buffer已通过DMA全部传输完成
                if( TxCpltFlag == 1 )
                {
                        while( 1 )
                        {
                                nSamples = SpiritMP3Decode( &g_MP3Decoder,                                                                                             /* Decoder structure */
                                                                                                                                                (short *)&audio_output_buffer[MPEGAudioFrameInfo.mSamplesPerFrame*2],                                           /* [OUT] Output PCM buffer */
                                                                                                                                                MPEGAudioFrameInfo.mSamplesPerFrame,          /* Number of samples to decode (1 sample = 32 bit = 2ch*16 bit) */
                                                                                                                                                &MP3Info                                                                                            /* [OUT, opt] Optional informational structure */
                                                                                                                                        );        

                                /*到达文件末尾,则退出*/
                                if( nSamples < MPEGAudioFrameInfo.mSamplesPerFrame )
                                {
                                        BSP_AUDIO_OUT_Stop(CODEC_PDWN_SW);
                                        f_close( &file_object );
                                        return 1;
                                }
                                
                                if( !( !MP3Info.IsGoodStream || (MP3Info.nBitrateKbps == 0) || (MP3Info.nSampleRateHz == 0) ) )
                                {
                                        break;
                                }
                        }
                }
               
                if( TxHalfCpltFlag == 1 && TxCpltFlag == 1 )
                {
                        TxHalfCpltFlag = 0;
                        TxCpltFlag = 0;
                        
                        BSP_AUDIO_OUT_Resume(0);
                }
                else if( TxHalfCpltFlag == 1 ) TxHalfCpltFlag = 0;
                else if( TxCpltFlag == 1 ) TxCpltFlag = 0;
               
                AudioOutFlag = 1;
        }
        
        return 1;
}
七、中断处理

void DMA2_Stream1_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2_Stream1_IRQn 0 */

        HAL_DMA_IRQHandler(haudio_out_sai.hdmatx);
  /* USER CODE END DMA2_Stream1_IRQn 0 */

  /* USER CODE BEGIN DMA2_Stream1_IRQn 1 */

  /* USER CODE END DMA2_Stream1_IRQn 1 */
}
回调
void  BSP_AUDIO_OUT_TransferComplete_CallBack(uint32_t Instance)
{
        TxCpltFlag = 1;
        AudioOutFlag = 0;
        TxBufNum = 0;
        //printf("BSP_AUDIO_OUT_TransferComplete_CallBack\r\n");
        if( TxHalfCpltFlag == 1 )
        {
                BSP_AUDIO_OUT_Pause(0);
                TxBufNum = 1;
                printf("fault1\r\n");
        }
}        

void  BSP_AUDIO_OUT_HalfTransfer_CallBack(uint32_t Instance)
{
        TxHalfCpltFlag = 1;
        AudioOutFlag = 0;
        TxBufNum = 1;
        //printf("BSP_AUDIO_OUT_HalfTransfer_CallBack\r\n");
        if( TxCpltFlag == 1 )
        {
                BSP_AUDIO_OUT_Pause(0);
                TxBufNum = 0;
                printf("fault2\r\n");
        }
}


八、播放DEMO
void mp3_player_demo(void)
{
        if( st_mp3_player_Init( mp3Files[mp3Current%mp3Count], 80, 0) == 1 )
        {
                printf("mp3 init ok\r\n");
                st_mp3play( 0 );
        }
}
void BSP_PB_Callback(Button_TypeDef Button)
{
        printf("BSP_PB_Callback\r\n");
        if(Button==BUTTON_USER)
        {
                mp3Current++;
                if(mp3Current>=mp3Count) mp3Current=0;
               
        }
}
按键处理

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

51

主题

101

帖子

0

粉丝