?? atmel mp3.c
字號:
--------------------------------------------
*/
static void PllInit(void);
static void MP3Init(void);
static void AudioInit();
void MP3_Init();
void PlayInit(unsigned char *SongName);
void Func();
void Next();
void Previous();
void PlayPause();
void PlayMP3(unsigned char *SongName);
void KeyBoardInit();
void MP3FsInit(unsigned char NDIV, unsigned int RDIV, unsigned char MPCD, unsigned char AUCD)
{
PLLNDIV = 0;
PLLRDIV = 0;
MP3CLK = 0;
AUDCLK = 0;
//PLL時鐘的頻率計算方法
//PLLclk=(OSCclk*(RDIV+1))/(int)(NDIV+1);
//set PLL CLK
PLLNDIV = 0x7f&NDIV; //set NDIV
PLLCON |= (0x3&RDIV) << 6; //set RDIV
PLLRDIV = (0x3ff&RDIV) >> 2;
//MP3時鐘頻率的計算方法
//MP3CLK=PLLCLK/(int)(MPCD+1)負反饋
MP3CLK |= MPCD; //0000 0010 MPCD=2
//必須通過計算得到最小 MP3CLK 24M
//AUDCLK計算公式
//AUDCLK=PLLCLK/(int)(AUCD+1)負反饋
AUDCLK |= AUCD; //AUCD=4 必須通過計算得到 AUDCLK=12.288MHz
}
void PllInit(void)
{
if (FirstStart)
{
AUXR1 = 0xf2; //這兩個寄存器的值在用Start Application和直接上電時
//不一樣,前一種情況下MP3解碼器才工作,
PLLCON = 0; //這里強制將其置為與用Start Application按鈕時一致
FirstStart = 0;
}
//鎖相環時鐘及MP3解碼器時鐘設置
CKCON |= X2; //0000 0001使能X2模式,增加處理速度,
//每個機器周期變成6個振蕩周期即3個時鐘周期
PLLCON &= (~PLLRES); //Enable PLL
PLLCON |= PLLEN;
}
void MP3Init(void)
{
//MP3音量及音效初始值
MP3VOR = 0x0a; //0000 1111下同
MP3VOL = 0x0a;
MP3BAS = 0x0f;
MP3MED = 0x0f;
MP3TRE = 0x0f;
//MP3CON自動上電為0011 1111
MP3CON &= (~MSKREQ); //允許產生MP3中斷Clear to allow the
//MPREQ flag to generate a MP3 interrupt.
MP3CON |= MPEN; //使能MP3解碼器Set to enable the MP3 decoder.
}
void AudioInit()
{
unsigned char i = 10;
AUDCON0 = 0x77; //0111 0110
AUDCON1 &= (~0xB0); //SRC=0,MSREQ=0,MUDRN=0
AUDCON1 |= 0x01;
while (i)i--;
AUDCON1 |= 0x40;
}
void MP3_Init(void)
{
PllInit();
MP3Init();
AudioInit();
}
void PlayInit(unsigned char *SongName)
{
int i = 0, j = 0, f = 0;
int k = 0;
unsigned int total_size;
/* 分析MP3信息,可能會比較長,但是沒有別的辦法
先要讀出一部分文件內容,大小不能確定 */
m = ReadSector(SongName, Page_Buf); //先讀出512字節
/* when the first 3 bytes are 49 44 33 the next can be 03,this means ID3 V2.3 */
if (Page_Buf[0] == 0x49)
if ((Page_Buf[1] == 0x44) && (Page_Buf[2] == 0x33))
{
/********** search the 7th-10th bytes,use the formular to calculate ***********/
total_size = (Page_Buf[6] & 0x7F) * 0x200000 + (Page_Buf[7] & 0x7F) * 0x4000 + (Page_Buf[8] & 0x7F) * 0x80 + (Page_Buf[9] & 0x7F);
while (total_size > 512)
{
ReadSector(SongName, Page_Buf);
total_size -=512;
}
i = total_size;
}
//如果接下來是FFF則為MP3幀頭,如果
//不是則為擴展標簽頭,需要加10個字節的量
if (Page_Buf[i] != 0xFF)
i += 10;
if ((Page_Buf[i] == 0xFF) && (Page_Buf[i + 1] & 0xF0 == 0xF0))//get MP3 information from FF FX XX XX 4bytes,
//and show that
{
MP3_Framehead[0] = Page_Buf[i];
MP3_Framehead[1] = Page_Buf[i + 1];
MP3_Framehead[2] = Page_Buf[i + 2];
MP3_Framehead[3] = Page_Buf[i + 3];
}
if (MP3_Framehead[1] & 0x08)
{
MP3_Init();
switch ((MP3_Framehead[2] & 0x0C) >> 2)
{
case 0x00 : MP3FsInit(24, 126, 3, 5); break; //Fs=44.1kHz
case 0x01 : MP3FsInit(124, 575, 3, 4); break; //Fs=48kHz
case 0x02 : MP3FsInit(124, 511, 3, 9); AUDCON0 = 0x76; break;//Fs=32kHz
default : break;
}
}
else
{
MP3_Init();
switch ((MP3_Framehead[2] & 0x0C) >> 2)
{
case 0x00 : MP3FsInit(24, 126, 3, 11); break; //Fs=22.05kHz
case 0x01 : MP3FsInit(124, 575, 3, 9); break; //Fs=24kHz
case 0x02 : MP3FsInit(124, 511, 3, 19); AUDCON0 = 0x76; break; //Fs=16kHz
default : break;
}
}
DataRead = 0; //這句一定要加上
}
void PlayMP3(unsigned char *SongName)
{
int i =0;
while (MP3STA1&MPFREQ)
{
//MP3解碼器請求數據塊
m = ReadSector(SongName, Page_Buf); //從當前歌曲中讀取512字節
for (i=0; i<m; i++)
{
while (!(MP3STA1 & MPBREQ))
{ //MP3解碼器請求數據字節
while (!PlayState); //暫停播放
if (ChangeSong)
{ //發生選曲
DataRead = 0;
ChangeSong = 0;
return;
}
}
MP3DAT = Page_Buf[i]; //向MP3解碼器數據寄存器送入一個數據字節
}
if (m < 512)
{ //如果從歌曲中讀出的數據不足512個字節則結束本歌曲播放
NowPlaying++;
MP3InitFlag = 1;
return;
}
}
}
void KeyBoardInit()
{
P1 = 0x0f; //將端口1的低四位,即鍵盤對應的4位置1
KBCON = 0x00; //設置鍵盤有效模式為低電平有效,并使能
//中斷Low Level,Enable Interrupt
IEN1 = IEN1 | EKB; //使能鍵盤中斷Enable KeyBoard Interrupt
}
void Func()
{
if (CurrentFun < 3)
{
CurrentFun++; //在選曲/音量調節/音效調節三者間切換
}
else if (CurrentFun == 3)
{
CurrentFun = 1;
}
}
void Next() //按下"下一首/音量減小"鍵時的處理
{
switch (CurrentFun)
{ //如果當前處于音量調節功能
case VOLUME :
{
if (MP3VOR > 0x00) //當前音量沒有達到最小時
{
MP3VOR -= 0x01; //右聲道音量增大一檔
MP3VOL -= 0x01; //左聲道音量增大一檔
}
break;
}
case EFFECTION : //如果處于音效調節功能
{
if (MP3BAS > 7)
{ //降低重音效果
MP3BAS -= 7;
MP3MED = 0x0f;
MP3TRE += 7;
}
break;
}
case SELECTSONG : //如果處理MP3選取功能
{
if (NowPlaying == (NumofSong - 1))
{
NowPlaying = 0; //如果已經處于最后一首了,則指向第一首
MP3InitFlag = 1;
}
else
{
NowPlaying++; //否則,指向下一首
MP3InitFlag = 1;
}
ChangeSong = 1; //置選曲標志位
break;
}
default : break;
}
}
void Previous() //按下"上一首/音量增大"鍵時的處理
{
switch (CurrentFun)
{
case VOLUME : //如果當前處于音量調節功能
{
if (MP3VOR < 0x1f) //當前音量沒有達到最大時
{
MP3VOR += 0x01; //右聲道音量增大一檔
MP3VOL += 0x01; //左聲道音量增大一檔
}
break;
}
case EFFECTION : //如果處于音效調節功能
{
if (MP3BAS < 0x1e)
{ //增加重音效果
MP3BAS += 5;
MP3MED = 0x0f;
MP3TRE -= 5;
}
break;
}
case SELECTSONG : //如果處理MP3選取功能
{
if (NowPlaying > 0)
{
NowPlaying--; //如果當前播放歌曲不為第一首,則指向上一首
MP3InitFlag = 1;
}
else
{
NowPlaying = NumofSong - 1; //如果當前已經到達第一首,則指向最后一首
MP3InitFlag = 1;
}
ChangeSong = 1; //置選曲標志位
break;
}
default:break;
}
}
void PlayPause()
{
PlayState = !PlayState; //按一下播放鍵時,改變播放狀態
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -