|
|
84-MP3播放器,STC32G144K246实验箱演示程序
主程序main.C代码如下(汇编版本在附件中):
/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com -----------------------------------------*/
/*---------------------------------------------------------------------*/
/************* 功能说明 **************
音频文件:
16k单声道mp3文件或16k16位小端双声道PCM文件
ffmpeg pcm转码:
ffmpeg -ss 00:01:10 -t 45 -i .\x.mp3 -vn -ac 2 -f s16le -ar 16000 -acodec pcm_s16le out.pcm
ffmpeg mp3转码:
ffmpeg -i .\x.mp3 -vn -c:a libmp3lame -ar 16000 -b:a 32k -ac 1 -joint_stereo 0 out.mp3
简易命令:
test:执行FATFS初始化
ls:文件列表
play x:播放指定文件,x为ls列表序号
stop:停止播放
stat:状态信息打印
SD卡:
使用电脑格式化为FAT32格式或,使用test命令在实验箱上初始化
放入SD卡音频文件使用字母+数字命名,不要使用中文。
下载时, 选择时钟 48MHz
******************************************/
#include "config.h"
#include "I2S.h"
#include "TLV320AIC23.h"
#include "audio.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "spi.h"
#include "file_system.h"
void sys_init();
void print_status();
void CLK_Init(void);
void play();
void main()
{
sys_init(); // 系统初始化
CLK_Init(); // 时钟初始化
fsInitFlag = 0;
aInfo.isPlay = 0;
SPI_Init();
Timer0_Init();
AIC23_Init();
delay_ms(50);
AIC32_InitSet();
SetHeadPhoneVolume(60); // 设置音量
I2S_Init();
delay_ms(5);
usb_init(); // USB初始化
delay_ms(5);
EA = 1;
while (DeviceState != DEVSTATE_CONFIGURED)
{
}; // 等待USB完成配置
delay_ms(1000);
memset(UsbOutBuffer, 0, 64);
while (1)
{
audio_play_run();
if (bUsbOutReady)
{
printf("%s\n", UsbOutBuffer);
if (strncmp(UsbOutBuffer, "test", 4) == 0)
{
if (!file_sys_init(FATFS_SD_PATH))
{
printf("fs初始化失败\n");
}
else
{
fatFsTest(FATFS_SD_PATH);
}
}
else if (strncmp(UsbOutBuffer, "ls", 2) == 0)
{
if (!file_sys_init(FATFS_SD_PATH))
{
printf("文件系统初始化失败\n");
}
else
{
list_files(FATFS_SD_PATH);
}
}
else if (strncmp(UsbOutBuffer, "play", 4) == 0)
{
play();
}
else if (strncmp(UsbOutBuffer, "stat", 4) == 0)
{
print_status();
}
else if (strncmp(UsbOutBuffer, "stop", 4) == 0)
{
aInfo.isPlay = 0;
f_close(&audio_file);
printf("播放已停止\n");
}
else
{
printf("USB OUT DONE\r\n");
}
memset(UsbOutBuffer, 0, 64);
usb_OUT_done(); // 接收应答(固定格式)
}
}
}
extern u16 mp3_data_offset;
extern u16 mp3_data_sum;
extern volatile u8 pcm_run_flag;
extern u16 i2s_buffer_len;
extern u16 i2s_buffer_index;
void print_status(){
printf("status:\n");
printf("pcm_run_flag:%u\n",pcm_run_flag);
printf("mp3_data_sum:%u\n",mp3_data_sum);
printf("mp3_data_offset:%u\n",mp3_data_offset);
printf("i2s_buffer_len:%u\n",i2s_buffer_len);
printf("i2s_buffer_index:%u\n",i2s_buffer_index);
};
void sys_init()
{
EnableAccessXFR(); //使能访问扩展XFR
AccessCodeFastest(); //设置最快速度访问程序代码
AccessIXramFastest(); //设置最快速度访问内部XDATA
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
P0M1 = 0x00;
P0M0 = 0x00;
P1M1 = 0x00;
P1M0 = 0x00;
P2M1 = 0x00;
P2M0 = 0x00;
P3M1 = 0x00;
P3M0 = 0x00;
P4M1 = 0x00;
P4M0 = 0x00;
P5M1 = 0x00;
P5M0 = 0x00;
P6M1 = 0x00;
P6M0 = 0x00;
P7M1 = 0x00;
P7M0 = 0x00;
P1SR = 0;
P2SR = 0;
P7SR = 0; // 设置为高速模式
//TFT SPI1
// P2M0 = 0x7c; P2M1 = 0x00; //P22~P25 推挽
// //P2PU = 0xFF; //使能所有的QSPI口的内部10K上拉电阻
// P2SR = 0xc3;
// P2DR = 0xc3;
//I2S AIC23_Init中定义
// FLASH USART4_ SPI 3
P7M0 = 0x0b;
P7M1 = 0x00; // 70 71 73 推挽
P7PU = 0xFF; // 使能所有的QSPI口的内部10K上拉电阻
// // TFT\SD SPI1
P2M0 = 0x6c;
P2M1 = 0x93; // P22\P23\P25\P26 推挽
P2PU = 0xFF;
P2SR = 0x93;
P2DR = 0x93;
// // P92 SD CS_PIN 推挽
P9M0 = 0x04;
P9M1 = 0xfb;
P9PU = 0x04;
// uart
P3M0 = 0x80; P3M1 = 0x7f;
}
////////////////////////////////////////
// 时钟初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void CLK_Init(void)
{
CLK_I2S1CLK_Divider(2); //设置I2S1时钟预分频系数
CLK_I2S2CLK_Divider(1); //设置I2S2时钟预分频系数
CLK_SPI1CLK_Divider(5); //设置SPI1时钟预分频系数
CLK_SPI2CLK_Divider(1); //设置SPI2时钟预分频系数
CLK_SPI3CLK_Divider(1); //设置SPI3时钟预分频系数
CLK_PWMACLK_Divider(1); //设置PWMA时钟预分频系数
CLK_PWMBCLK_Divider(1); //设置PWMB时钟预分频系数
CLK_PWMCCLK_Divider(1); //设置PWMC时钟预分频系数
CLK_PWMDCLK_Divider(1); //设置PWMD时钟预分频系数
CLK_PWMECLK_Divider(1); //设置PWME时钟预分频系数
CLK_PWMFCLK_Divider(1); //设置PWMF时钟预分频系数
CLK_TFPUCLK_Divider(1); //设置TFPU时钟预分频系数
CLK_SYSCLK_Divider(10); //切换主时钟前先将系统时钟降频
HIRC_48M(); //选择内部预置的频率
CLK_MCLK_HIRC(); //选择内部高精度HIRC作为主时钟
CLK_HPLL1_BASECLK(); //选择内部基本时钟BASECLK作为HPLL1输入时钟
CLK_HPLL1_PreDivider(8); //设置HPLL1的输入时钟预分频系数(分频后的频率必须为6MHz左右)
CLK_HPLL1_Lock408MHz(); //选择HPLL1的锁频目标频率
CLK_HPLL1_Enable(); //启动HPLL1
delay_ms(1); //等待PLL锁频
CLK_MCLK2_HPLL1D2(); //选择HPLL1的输出2分频时钟作为主时钟
CLK_SYSCLK_Divider(2); //设置系统时钟分频系数
CLK_HSI2SCK_HPLL1D2(); //选择HPLL1的输出2分频时钟作为高速I2S时钟源
CLK_HSIOCK_HPLL1D2(); //选择HPLL1的输出2分频时钟作为高速外设时钟源
//<<AICUBE_USER_CLOCK_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_CLOCK_INITIAL_END>>
}
void delay_ms(WORD ms)
{
WORD i;
do
{
i = MAIN_Fosc / 6000;
while (--i)
;
} while (--ms);
}
void delay_us(WORD ms)
{
WORD i;
do
{
i = MAIN_Fosc / 6000000UL;
while (--i)
;
} while (--ms);
}
void QSPI_DMA_Isr() interrupt DMA_QSPI_VECTOR
{
DMA_QSPI_STA = 0x00;
// //DMA_P2P1_CR1 = 0; // 关闭P2P
// DMA_P2P1_SRC = 0;
// DMA_P2P1_DEST = 0;
// SPSTAT = 0x80 + 0x40; // 清0 SPIF和WCOL标志
// HSSPI_DisableFIFO(); // 使用SPI查询或中断方式时,要禁止FIFO
// lcd_cs_pin = 1;
// qspiDmaFlag = 1;
printf("DMA END\n");
}
void play()
{
char *cmd_param = UsbOutBuffer + 5;
u16 file_index = atoi(cmd_param);
file_index--;
if (aInfo.isPlay)
{
printf("请先停止当前播放\n");
return;
}
if (!file_sys_init(FATFS_SD_PATH))
{
printf("文件系统初始化失败\n");
}
else
{
// 如果文件列表为空,先获取文件列表
if (file_list_count == 0)
{
list_files(FATFS_SD_PATH);
}
// 获取指定索引的文件路径
memset(aInfo.file_name, 0, sizeof(aInfo.file_name));
if (get_file_by_index(file_index, aInfo.file_name))
{
FRESULT res;
printf("play: %s\n", aInfo.file_name);
// 这里将调用audio.c中的函数来播放音频
// 首先需要打开文件,获取文件大小
res = f_open(&audio_file, aInfo.file_name, FA_READ);
if (res == FR_OK)
{
DWORD file_size = f_size(&audio_file);
// 初始化音频播放
aInfo.audio_size = file_size;
aInfo.audio_index = 0;
aInfo.isPlay = 1;
audio_play_init();
}
else
{
memset(aInfo.file_name, 0, sizeof(aInfo.file_name));
printf("open file %s fail: %u\n", aInfo.file_name, res);
}
}
}
}
84-MP3播放器.zip
(14.91 MB, 下载次数: 51)
|
|