久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2444|回復: 0
打印 上一主題 下一主題
收起左側

基于單片機的音樂播放

[復制鏈接]
跳轉到指定樓層
樓主
#include "MusicPlay.h"
unsigned char *PP[]={song1,song2,song3};//指向歌曲的指針數組
unsigned char *p;//只想歌曲的指針
unsigned int Point = 0;//歌曲播放位置
bit flag_pause=1;//暫停標志位
bit flag_up=0;//上一曲標志位
bit flag_down=0;//下一曲標志位
int flag_order=0;//歌曲順序
void Delay1ms(unsigned int count);//簡單延時
void InitialSound(void);//初始化
void Play(unsigned char *sound,unsigned char Signature,unsigned Octachord,unsigned int Speed);//音樂播放函數
//******************主程序***************************************************
void main()
{
    InitialSound();
    while(1)
    {
        if(k_state==0)//有按鍵按下
        {
            if(k_pause==0)//開始/暫停鍵
            {
                while(k_pause==0);
                flag_pause=~flag_pause;
            }
        }
        while(!flag_pause)
        {
            Play(p+Point,0,3,360);
            Delay1ms(300);
            if(flag_down | flag_up)
            {
                if(flag_down) flag_down=0;
                if(flag_up)   flag_up  =0;
                Point = 0;
            }
            else flag_order++;
            if(flag_pause==1) flag_order--;
        
            if(flag_order == 3)
                flag_order = 0;
            p=PP[flag_order];   
        }
    }
}
//***********************中斷服務程序*************************************//
void BeepTimer0(void) interrupt 1   //音符中斷程序
{
    BeepIO = !BeepIO;
    TH0    = Sound_Temp_TH0;
    TL0    = Sound_Temp_TL0;
}
//***********************簡單延時*******************************************//
void Delay1ms(unsigned int count)
{
    unsigned int i,j;
    for(i=0;i<count;i++)
    for(j=0;j<120;j++);
}
//***********************系統初始化********************************************//
void InitialSound(void)
{
    BeepIO = 0;
    Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256;   // 計算TL1應裝入的初值  (10ms的初裝值)
    Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256;   // 計算TH1應裝入的初值
    TH1 = Sound_Temp_TH1;
    TL1 = Sound_Temp_TL1;
    TMOD  |= 0x11;
    ET0    = 1;
    ET1    = 0;
    TR0    = 0;
    TR1    = 0;
    EA     = 1;
    p=PP[0];
}
/****************************音樂播放函數***************************************/
/*  input:歌曲名sound
                    調號signature
          音階octachord
                    速度speed
*/
void Play(unsigned char *sound,unsigned char Signature,unsigned Octachord,unsigned int Speed)
{
    unsigned int NewFreTab[12];//新的頻率表
    unsigned char i,j;
    unsigned int LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
    unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;
    if(p==song1) flag_order=0;
    else if (p==song2) flag_order=1;
    else if (p==song3)  flag_order=2;
    for(i=0;i<12;i++)// 根據調號及升降八度來生成新的頻率表
    {
        j = i + Signature;
        if(j > 11)
        {
            j = j-12;
            NewFreTab[i] = FreTab[j]*2;
        }
        else
            NewFreTab[i] = FreTab[j];
        if(Octachord == 1)
            NewFreTab[i]>>=2;
        else if(Octachord == 3)
            NewFreTab[i]<<=2;
    }                                   
    SoundLength = 0;
    while(sound[SoundLength] != 0x00)   //計算歌曲長度
    {
        SoundLength+=2;
    }
//  Point = 0;
    Tone   = sound[Point];
    Length = sound[Point+1];            // 讀出第一個音符和它時時值
   
    LDiv0 = 12000/Speed;                // 算出1分音符的長度(幾個10ms)
    LDiv4 = LDiv0/4;                    // 算出4分音符的長度
    LDiv4 = LDiv4-LDiv4*SOUND_SPACE;    // 普通音最長間隔標準
    TR0   = 0;
    TR1   = 1;
    while(Point < SoundLength)
    {
        SL=Tone%10;                                 //計算出音符
        SM=Tone/10%10;                              //計算出高低音
        SH=Tone/100;                                //計算出是否升半
        CurrentFre = NewFreTab[SignTab[SL-1]+SH];   //查出對應音符的頻率     
        if(SL!=0)
        {
            if (SM==1) CurrentFre >>= 2;        //低音
            if (SM==3) CurrentFre <<= 2;        //高音
            Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//計算計數器初值
            Sound_Temp_TH0 = Temp_T/256;
            Sound_Temp_TL0 = Temp_T%256;
            TH0 = Sound_Temp_TH0;  
            TL0 = Sound_Temp_TL0 + 12; //加12是對中斷延時的補償
        }
        SLen=LengthTab[Length%10];  //算出是幾分音符
        XG=Length/10%10;            //算出音符類型(0普通1連音2頓音)
        FD=Length/100;
        LDiv=LDiv0/SLen;            //算出連音音符演奏的長度(多少個10ms)
        if (FD==1)
            LDiv=LDiv+LDiv/2;
        if(XG!=1)
            if(XG==0)               //算出普通音符的演奏長度
                if (SLen<=4)   
                    LDiv1=LDiv-LDiv4;
                else
                    LDiv1=LDiv*SOUND_SPACE;
            else
                LDiv1=LDiv/2;       //算出頓音的演奏長度
        else
            LDiv1=LDiv;
        if(SL==0) LDiv1=0;
            LDiv2=LDiv-LDiv1;       //算出不發音的長度
      if (SL!=0)
        {
            TR0=1;
            for(i=LDiv1;i>0;i--)    //發規定長度的音
            {
                while(TF1==0);
                TH1 = Sound_Temp_TH1;
                TL1 = Sound_Temp_TL1;
                TF1=0;
            }
        }
        if(LDiv2!=0)
        {
            TR0=0; BeepIO=0;
            for(i=LDiv2;i>0;i--)    //音符間的間隔
            {
                while(TF1==0);
                TH1 = Sound_Temp_TH1;
                TL1 = Sound_Temp_TL1;
                TF1=0;
            }
        }
        Point+=2;
        Tone=p[Point];
        Length=p[Point+1];
//按鍵掃描
        if(k_state==0)
        {//掃描開始
            if(k_pause==0)
            {
                while(k_pause==0);
                flag_pause=~flag_pause;
                TR1   = flag_pause;
                return;
            }
            if(k_up==0)
            {
                while(k_up==0);
                flag_up=~flag_up;
                flag_order--;
                if(flag_order < 0)
                    flag_order = 2;//第三首
                 p=PP[flag_order];
                break;
            }
            if(k_down==0)
            {
                while(k_down==0);
                flag_down=~flag_down;
                flag_order++;
                if(flag_order > 2)
                    flag_order=0;//第一首
                 p=PP[flag_order];
                break;
            }
        }//按鍵掃描結束
    }
    BeepIO = 0;//播放結束,關閉
}#include "MusicPlay.h"
unsigned char *PP[]={song1,song2,song3};//指向歌曲的指針數組
unsigned char *p;//只想歌曲的指針
unsigned int Point = 0;//歌曲播放位置
bit flag_pause=1;//暫停標志位
bit flag_up=0;//上一曲標志位
bit flag_down=0;//下一曲標志位
int flag_order=0;//歌曲順序
void Delay1ms(unsigned int count);//簡單延時
void InitialSound(void);//初始化
void Play(unsigned char *sound,unsigned char Signature,unsigned Octachord,unsigned int Speed);//音樂播放函數
//******************主程序***************************************************
void main()
{
    InitialSound();
    while(1)
    {
        if(k_state==0)//有按鍵按下
        {
            if(k_pause==0)//開始/暫停鍵
            {
                while(k_pause==0);
                flag_pause=~flag_pause;
            }
        }
        while(!flag_pause)
        {
            Play(p+Point,0,3,360);
            Delay1ms(300);
            if(flag_down | flag_up)
            {
                if(flag_down) flag_down=0;
                if(flag_up)   flag_up  =0;
                Point = 0;
            }
            else flag_order++;
            if(flag_pause==1) flag_order--;
        
            if(flag_order == 3)
                flag_order = 0;
            p=PP[flag_order];   
        }
    }
}
//***********************中斷服務程序*************************************//
void BeepTimer0(void) interrupt 1   //音符中斷程序
{
    BeepIO = !BeepIO;
    TH0    = Sound_Temp_TH0;
    TL0    = Sound_Temp_TL0;
}
//***********************簡單延時*******************************************//
void Delay1ms(unsigned int count)
{
    unsigned int i,j;
    for(i=0;i<count;i++)
    for(j=0;j<120;j++);
}
//***********************系統初始化********************************************//
void InitialSound(void)
{
    BeepIO = 0;
    Sound_Temp_TH1 = (65535-(1/1200)*SYSTEM_OSC)/256;   // 計算TL1應裝入的初值  (10ms的初裝值)
    Sound_Temp_TL1 = (65535-(1/1200)*SYSTEM_OSC)%256;   // 計算TH1應裝入的初值
    TH1 = Sound_Temp_TH1;
    TL1 = Sound_Temp_TL1;
    TMOD  |= 0x11;
    ET0    = 1;
    ET1    = 0;
    TR0    = 0;
    TR1    = 0;
    EA     = 1;
    p=PP[0];
}
/****************************音樂播放函數***************************************/
/*  input:歌曲名sound
                    調號signature
          音階octachord
                    速度speed
*/
void Play(unsigned char *sound,unsigned char Signature,unsigned Octachord,unsigned int Speed)
{
    unsigned int NewFreTab[12];//新的頻率表
    unsigned char i,j;
    unsigned int LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength;
    unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD;
    if(p==song1) flag_order=0;
    else if (p==song2) flag_order=1;
    else if (p==song3)  flag_order=2;
    for(i=0;i<12;i++)// 根據調號及升降八度來生成新的頻率表
    {
        j = i + Signature;
        if(j > 11)
        {
            j = j-12;
            NewFreTab[i] = FreTab[j]*2;
        }
        else
            NewFreTab[i] = FreTab[j];
        if(Octachord == 1)
            NewFreTab[i]>>=2;
        else if(Octachord == 3)
            NewFreTab[i]<<=2;
    }                                   
    SoundLength = 0;
    while(sound[SoundLength] != 0x00)   //計算歌曲長度
    {
        SoundLength+=2;
    }
//  Point = 0;
    Tone   = sound[Point];
    Length = sound[Point+1];            // 讀出第一個音符和它時時值
   
    LDiv0 = 12000/Speed;                // 算出1分音符的長度(幾個10ms)
    LDiv4 = LDiv0/4;                    // 算出4分音符的長度
    LDiv4 = LDiv4-LDiv4*SOUND_SPACE;    // 普通音最長間隔標準
    TR0   = 0;
    TR1   = 1;
    while(Point < SoundLength)
    {
        SL=Tone%10;                                 //計算出音符
        SM=Tone/10%10;                              //計算出高低音
        SH=Tone/100;                                //計算出是否升半
        CurrentFre = NewFreTab[SignTab[SL-1]+SH];   //查出對應音符的頻率     
        if(SL!=0)
        {
            if (SM==1) CurrentFre >>= 2;        //低音
            if (SM==3) CurrentFre <<= 2;        //高音
            Temp_T = 65536-(50000/CurrentFre)*10/(12000000/SYSTEM_OSC);//計算計數器初值
            Sound_Temp_TH0 = Temp_T/256;
            Sound_Temp_TL0 = Temp_T%256;
            TH0 = Sound_Temp_TH0;  
            TL0 = Sound_Temp_TL0 + 12; //加12是對中斷延時的補償
        }
        SLen=LengthTab[Length%10];  //算出是幾分音符
        XG=Length/10%10;            //算出音符類型(0普通1連音2頓音)
        FD=Length/100;
        LDiv=LDiv0/SLen;            //算出連音音符演奏的長度(多少個10ms)
        if (FD==1)
            LDiv=LDiv+LDiv/2;
        if(XG!=1)
            if(XG==0)               //算出普通音符的演奏長度
                if (SLen<=4)   
                    LDiv1=LDiv-LDiv4;
                else
                    LDiv1=LDiv*SOUND_SPACE;
            else
                LDiv1=LDiv/2;       //算出頓音的演奏長度
        else
            LDiv1=LDiv;
        if(SL==0) LDiv1=0;
            LDiv2=LDiv-LDiv1;       //算出不發音的長度
      if (SL!=0)
        {
            TR0=1;
            for(i=LDiv1;i>0;i--)    //發規定長度的音
            {
                while(TF1==0);
                TH1 = Sound_Temp_TH1;
                TL1 = Sound_Temp_TL1;
                TF1=0;
            }
        }
        if(LDiv2!=0)
        {
            TR0=0; BeepIO=0;
            for(i=LDiv2;i>0;i--)    //音符間的間隔
            {
                while(TF1==0);
                TH1 = Sound_Temp_TH1;
                TL1 = Sound_Temp_TL1;
                TF1=0;
            }
        }
        Point+=2;
        Tone=p[Point];
        Length=p[Point+1];
//按鍵掃描
        if(k_state==0)
        {//掃描開始
            if(k_pause==0)
            {
                while(k_pause==0);
                flag_pause=~flag_pause;
                TR1   = flag_pause;
                return;
            }
            if(k_up==0)
            {
                while(k_up==0);
                flag_up=~flag_up;
                flag_order--;
                if(flag_order < 0)
                    flag_order = 2;//第三首
                 p=PP[flag_order];
                break;
            }
            if(k_down==0)
            {
                while(k_down==0);
                flag_down=~flag_down;
                flag_order++;
                if(flag_order > 2)
                    flag_order=0;//第一首
                 p=PP[flag_order];
                break;
            }
        }//按鍵掃描結束
    }
    BeepIO = 0;//播放結束,關閉
}


untitled.png (278.08 KB, 下載次數: 53)

untitled.png

音樂r.zip

18.57 KB, 下載次數: 10, 下載積分: 黑幣 -5

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久热久 | 日韩欧美一级片 | www.亚洲精品 | 国产四区| 91精品欧美久久久久久久 | 国产激情自拍视频 | 懂色中文一区二区在线播放 | 免费网站国产 | 性一交一乱一透一a级 | 欧美一区二区三区在线 | 2018国产大陆天天弄 | 日韩av中文| 国产乱人伦精品一区二区 | 偷拍自拍第一页 | 日本成人在线观看网站 | 91av在线电影 | 一区二区国产在线观看 | 粉嫩国产精品一区二区在线观看 | 成人午夜精品一区二区三区 | 亚洲免费一区二区 | 99精品国产一区二区三区 | 中文字幕一区二区在线观看 | 免费国产视频 | 97精品国产97久久久久久免费 | 特级一级黄色片 | 欧美久久一级 | 天天干狠狠操 | 激情视频中文字幕 | 福利久久 | 97人人澡人人爽91综合色 | 欧美一区二区三区 | 粉嫩一区二区三区国产精品 | 日韩不卡视频在线 | 久久黄色网| 日本精品视频在线观看 | 日韩在线视频一区 | 激情 婷婷 | 97伦理| 欧美日韩久久 | 高清久久久 | 亚洲一区中文字幕在线观看 |