找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 2296|回復(fù): 0
收起左側(cè)

51單片機(jī)MP3源碼

[復(fù)制鏈接]
ID:326100 發(fā)表于 2018-5-9 17:21 | 顯示全部樓層 |閱讀模式
/*************************************************************
    按鍵控制說明:
    按鍵 0 - 9 對(duì)應(yīng)最多10首樂曲,當(dāng)一首樂曲播放完畢后,
    響應(yīng)按鍵的動(dòng)作去播放相應(yīng)的音樂,另外,右、下這兩個(gè)按鍵
    對(duì)應(yīng)著下一首,左上這兩個(gè)按鍵對(duì)應(yīng)著上一首。
    日期:5月9日
*************************************************************/  
#include <reg52.h>  
#include <string.h>  
#define RldTmr(fr) 65536 - (11059200 / 12) / ((fr) << 1)  
#define FuDian(n) ((n) << 1) / 3    //附點(diǎn)n分音符的換算  

typedef unsigned char uchar;  
typedef unsigned int uint;  
typedef unsigned long ulong;  
typedef struct music {  
    char * pNote;  
    char * pDur;  
} Music;  

sbit BUZZ = P1^6;  

sbit KEY_OUT_3 = P2^0;  
sbit KEY_OUT_2 = P2^1;  
sbit KEY_OUT_1 = P2^2;  
sbit KEY_OUT_0 = P2^3;  
sbit KEY_IN_0 = P2^4;  
sbit KEY_IN_1 = P2^5;  
sbit KEY_IN_2 = P2^6;  
sbit KEY_IN_3 = P2^7;  

uint code noteFreq[] = {    //中音 1-7 和高音 1-7對(duì)應(yīng)的頻率列表 低音  
    523, 587, 659, 698, 784, 880, 988,  
    1047, 1175, 1319, 1397, 1568, 1760, 1976,  
    //261, 293, 329, 349, 392, 440, 494  
};  
uint code tmrRld[] = {      //中音 1-7 和高音 1-7對(duì)應(yīng)的定時(shí)器重載值  
    RldTmr(523), RldTmr(587), RldTmr(659), RldTmr(698), RldTmr(784), RldTmr(880), RldTmr(988),  
    RldTmr(1047), RldTmr(1175), RldTmr(1319), RldTmr(1397), RldTmr(1568), RldTmr(1760), RldTmr(1976),  
    //RldTmr(261), RldTmr(293), RldTmr(329), RldTmr(349), RldTmr(392), RldTmr(440), RldTmr(494)  
};  
uchar code keyCodeMap[4][4] = { //矩陣按鍵編號(hào)到標(biāo)準(zhǔn)鍵盤鍵碼的映射表  
    {0x31, 0x32, 0x33, 0x26}, //數(shù)字鍵1、數(shù)字鍵2、數(shù)字鍵3、向上鍵  
    {0x34, 0x35, 0x36, 0x25}, //數(shù)字鍵4、數(shù)字鍵5、數(shù)字鍵6、向左鍵  
    {0x37, 0x38, 0x39, 0x28}, //數(shù)字鍵7、數(shù)字鍵8、數(shù)字鍵9、向下鍵  
    {0x30, 0x1B, 0x0D, 0x27}  //數(shù)字鍵0、ESC鍵、  回車鍵、 向右鍵  
};  
uchar keyState[4][4] = {  //全部矩陣按鍵的當(dāng)前狀態(tài)  
    {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1},  {1, 1, 1, 1}  
};  
bit enable = 1, tmrFlg = 0;  
uchar T0RH = 0XFF, T0RL = 0X00;  
uchar T1RH, T1RL;  
uchar musicIdx = 0;  
uchar musicSpeed = 72;  
uchar nowMusic = 0;  
//bit enKey = 1;  

uchar code twoTigerNote[] = {      //音名  
    1, 2, 3, 1,  
    1, 2, 3, 1,  
    3, 4, 5,  
    3, 4, 5,  
    5, 6, 5, 4, 3, 1,  
    5, 6, 5, 4, 3, 1,  
    1, 5, 1,  
    1, 5, 1,  
    '\0'  
};  
uchar code twoTigerDuration[] = {       //音名對(duì)應(yīng)的時(shí)值,4表示4分音符,8表示8分音符,16表示16分音符  
    4, 4, 4, 4,  
    4, 4, 4, 4,  
    4, 4, 2,  
    4, 4, 2,  
    FuDian(8), 16, FuDian(8), 16, 4, 4,  
    FuDian(8), 16, FuDian(8), 16, 4, 4,  
    4, 4, 2,  
    4, 4, 2,  
    '\0'  
};  
uchar code baheNote[] = {  
    5, 1, 2, 3, 4,  
    5, 1, 1,  
    6, 4, 5, 6, 7,  
    8, 1, 1,  
    4, 5, 4, 3, 2,  
    3, 4, 3, 2, 1,  
    7, 1, 2, 3, 1,  
    3, 2,  
    5, 1, 2, 3, 4,  
    5, 1, 1,  
    6, 4, 5, 6, 7,  
    8, 1, 1,  
    4, 5, 4, 3, 2,  
    3, 4, 3, 2, 1,  
    2, 3, 2, 1, 7,  
    1,  
    '\0'  
};  
uchar code baheDur[] = {  
    4, 8, 8, 8, 8,  
    4, 4, 4,  
    4, 8 ,8 ,8, 8,  
    4, 4, 4,  
    4, 8, 8, 8, 8,  
    4, 8, 8, 8, 8,  
    4, 8, 8, 8, 8,  
    4, 2,  
    4, 8, 8, 8, 8,  
    4, 4, 4,  
    4, 8 ,8 ,8, 8,  
    4, 4, 4,  
    4, 8, 8, 8, 8,  
    4, 8, 8, 8, 8,  
    4, 8, 8, 8, 8,  
    4,  
    '\0'  
};  

uchar musicLen[10];  
Music musicSet[] = {  
    {twoTigerNote, twoTigerDuration},  
    {baheNote, baheDur},  
};  
uchar musicNum = sizeof(musicSet) / sizeof(Music);  

void delay(uint n);  
void playMusic(uchar musicIdx, uchar speed);    //固定標(biāo)準(zhǔn)為4分音符的速度:例如speed = 108 表示一分鐘掃過108個(gè)4分音符  
void setTmr1(uint ms);  
void keyScan();  
void keyAction();  
void keyDriver();  
void initMusicInfo();  

void main() {  
    initMusicInfo();  
    EA = 1;  
    TMOD = 0x01;  
    TH0 = T0RH;  
    TL0 = T0RL;  
    ET0 = 1;  
    PT0 = 1;  //重要!!設(shè)置T0搶占優(yōu)先級(jí)  

    //TR0 = 1;  
    setTmr1(10);  
    TH1 = T1RH;  
    TL1 = T1RL;  
    ET1 = 1;  

    TR0 = 1;  
    TR1 = 1;  
    while (1) {  
        //TR0 = 1;  
        playMusic(musicIdx, musicSpeed);  
        delay(40000u);  
    }  
}  

void initMusicInfo() {  
    uchar i;  
    for (i = 0; i < musicNum; i++) {  
        musicLen[i] = strlen(musicSet[i].pNote);  
    }  
}  

void delay(uint n) {  
    //uint i;  
    //TR1 = 1;  
    while (n--) {  
        keyDriver();  
    }  
    //TR1 = 0;  
}  

void playMusic(uchar musicIdx, uchar speed) {  
    uchar i;  
    uchar idx;  
    uint cnt = 0;  
    uint durationCnt = 0;   //當(dāng)前音符的時(shí)值對(duì)應(yīng)的定時(shí)器計(jì)數(shù)  
    uint soundCnt = 0;      //當(dāng)前音符的發(fā)聲時(shí)值對(duì)應(yīng)的計(jì)數(shù)值  
    char * musicNote = musicSet[musicIdx].pNote;  
    char * noteDuration = musicSet[musicIdx].pDur;  
    for (i = 0; i < musicLen[musicIdx]; ) {  
        while (!tmrFlg) ;  
        tmrFlg = 0;  
        //keyDriver(); //遞歸實(shí)現(xiàn)音樂的嵌套  
        if (cnt == 0) {  
            idx = musicNote[i] - 1;  
            T0RH = tmrRld[idx] >> 8;  
            T0RL = tmrRld[idx];  
            durationCnt = (ulong)240 * (ulong)noteFreq[idx] / ((ulong)noteDuration[i] * (ulong)speed);  
            soundCnt = durationCnt - (durationCnt >> 2);  //當(dāng)前音符時(shí)值的前3/4發(fā)聲,后1/4靜音  
            enable = 1;  
            cnt++;  
        }  
        else {  
            if (cnt == durationCnt) {  
                cnt = 0;  
                i++;  
            }  
            else {  
                cnt++;  
                if (cnt == soundCnt) {  
                    enable = 0;  
                }  
            }  
        }  
    }  
}  

void interruptTmr0() interrupt 1 {  
    TH0 = T0RH;  
    TL0 = T0RL;  
    tmrFlg = 1;  
    if (enable)  
        BUZZ = ~BUZZ;  
    else  
        BUZZ = 1;  
}  

void setTmr1(uint ms) {  
    ulong tmp;  
    tmp = 11059326 / 12;  
    tmp = tmp * ms / 1000;  
    tmp = 65536 - tmp;  
    tmp += 28;  
    T1RL = tmp;  
    T1RH = tmp >> 8;  
}  

void interruptTmr1() interrupt 3 {  
    TH1 = T1RH;  
    TL1 = T1RL;  
    //if (enKey)  
        keyScan();  
}  

void keyScan() {  
    static uchar i = 0;  
    static uchar keyBuf[4][4] = {  
        {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},  
        {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}  
    };  
    uchar j;  
    keyBuf[i][0] = (keyBuf[i][0] << 1) | KEY_IN_0;  
    keyBuf[i][1] = (keyBuf[i][1] << 1) | KEY_IN_1;  
    keyBuf[i][2] = (keyBuf[i][2] << 1) | KEY_IN_2;  
    keyBuf[i][3] = (keyBuf[i][3] << 1) | KEY_IN_3;  
    for (j=0; j<4; j++) {  
        if (keyBuf[i][j] == 0x00)  
            keyState[i][j] = 0;  
        else if (keyBuf[i][j] == 0xFF)  
            keyState[i][j] = 1;  
    }  
    switch (i) {  
        case 0: KEY_OUT_0 = 1; KEY_OUT_1 = 0; break;  
        case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;  
        case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;  
        case 3: KEY_OUT_3 = 1; KEY_OUT_0 = 0; break;  
        default : break;  
    }  
    i = ++i & 0x03;  
}  

void keyAction(uchar keyCode) {  
    if (keyCode >= 0x30 && keyCode <= 0x39) {  
        nowMusic = keyCode - 0x30;  
        if (nowMusic < musicNum) {  
            //TR1 = 0;  
            playMusic(nowMusic, musicSpeed);  
        }  
    }  
    else if (keyCode == 0x27 || keyCode == 0x28) {  
        if (nowMusic < musicNum - 1)  
            nowMusic++;  
        else  
            nowMusic = 0;  
        //TR1 = 0;  
        playMusic(nowMusic, musicSpeed);  
    }  
    else if (keyCode == 0x25 || keyCode == 0x26) {  
        if (nowMusic > 0)  
            nowMusic--;  
        else  
            nowMusic = musicNum - 1;  
        //TR1 = 0;  
        playMusic(nowMusic, musicSpeed);  
    }  
}  

void keyDriver() {  
    uchar i, j;  
    static uchar backup[4][4] = {  
        {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}  
    };  
    //if (enKey)  
        for (i=0; i<4; i++)  
            for (j=0; j<4; j++)  
                if (keyState[i][j] != backup[i][j]) {  
                    if (keyState[i][j] == 0) {  
                        keyAction(keyCodeMap[i][j]);  
                        //enKey = 0;  
                    }  
                backup[i][j] = keyState[i][j];  
            }  
}  

源碼.docx

19.86 KB, 下載次數(shù): 6, 下載積分: 黑幣 -5

51單片機(jī)MP3

回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表