找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2008|回复: 0
收起左侧

51单片机MP3源码

[复制链接]
ID:326100 发表于 2018-5-9 17:21 | 显示全部楼层 |阅读模式
/*************************************************************
    按键控制说明:
    按键 0 - 9 对应最多10首乐曲,当一首乐曲播放完毕后,
    响应按键的动作去播放相应的音乐,另外,右、下这两个按键
    对应着下一首,左上这两个按键对应着上一首。
    日期:5月9日
*************************************************************/  
#include <reg52.h>  
#include <string.h>  
#define RldTmr(fr) 65536 - (11059200 / 12) / ((fr) << 1)  
#define FuDian(n) ((n) << 1) / 3    //附点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对应的频率列表 低音  
    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对应的定时器重载值  
    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] = { //矩阵按键编号到标准键盘键码的映射表  
    {0x31, 0x32, 0x33, 0x26}, //数字键1、数字键2、数字键3、向上键  
    {0x34, 0x35, 0x36, 0x25}, //数字键4、数字键5、数字键6、向左键  
    {0x37, 0x38, 0x39, 0x28}, //数字键7、数字键8、数字键9、向下键  
    {0x30, 0x1B, 0x0D, 0x27}  //数字键0、ESC键、  回车键、 向右键  
};  
uchar keyState[4][4] = {  //全部矩阵按键的当前状态  
    {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[] = {       //音名对应的时值,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);    //固定标准为4分音符的速度:例如speed = 108 表示一分钟扫过108个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;  //重要!!!设置T0抢占优先级  

    //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;   //当前音符的时值对应的定时器计数  
    uint soundCnt = 0;      //当前音符的发声时值对应的计数值  
    char * musicNote = musicSet[musicIdx].pNote;  
    char * noteDuration = musicSet[musicIdx].pDur;  
    for (i = 0; i < musicLen[musicIdx]; ) {  
        while (!tmrFlg) ;  
        tmrFlg = 0;  
        //keyDriver(); //递归实现音乐的嵌套  
        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);  //当前音符时值的前3/4发声,后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, 下载次数: 6, 下载积分: 黑币 -5

51单片机MP3

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表