新聞中心

        EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 【C51】源碼 4 -- 喇叭播放【寒蟬鳴泣之時(shí)】插曲 You

        【C51】源碼 4 -- 喇叭播放【寒蟬鳴泣之時(shí)】插曲 You

        作者: 時(shí)間:2016-11-17 來(lái)源:網(wǎng)絡(luò) 收藏
        學(xué)單片機(jī)到喇叭部分,覺(jué)得挺好玩,編寫(xiě)了喇叭播放音樂(lè)的程序……

        BGM 取自【寒蟬鳴泣之時(shí)】插曲 You,簡(jiǎn)譜由網(wǎng)絡(luò)提供,感謝作者……先把簡(jiǎn)譜附上:

        本文引用地址:http://www.104case.com/article/201611/315360.htm

        還有一張自制的“鋼琴按鍵頻率分布”,沒(méi)寫(xiě)那么全,只對(duì)應(yīng)本程序,圖如下:

        附上源碼:(初出茅廬,難免有寫(xiě)的不好的地方,僅作備份之用,歡迎指點(diǎn),噴子退散……)

        /*******************************************************************
        喇叭播放音樂(lè)

        BGM 取自【寒蟬鳴泣之時(shí)】的插曲 You

        缺點(diǎn):

        1、沒(méi)有添加調(diào)節(jié)音量的功能
        2、音高、節(jié)拍 都要自己提前寫(xiě)好,工作量大
        可以改進(jìn)成:通過(guò)解析 midi 文件進(jìn)行音樂(lè)播放
        (midi 里邊就是音高、節(jié)拍信息)
        ********************************************************************/

        #include

        sbitSPK = P1^0;// 喇叭輸入

        /************************************************************************************************************************************
        PIANO_F[ ]:是鋼琴按鍵的頻率,數(shù)組下標(biāo)對(duì)應(yīng)鋼琴按鍵,如上圖所示
        例:圖上可以看出:8 號(hào)鍵對(duì)應(yīng)鋼琴的中央 C,正好是 PIANO_F[8],對(duì)應(yīng)頻率為 261.6 Hz
        注:PIANO_F[0] 不代表任何按鍵,為了方便計(jì)數(shù),數(shù)組下標(biāo)從 1 開(kāi)始有意義
        *************************************************************************************************************************************/

        float codePIANO_F[ ] = {7.63,
        130.8, 146.8, 164.8, 174.5, 196.0, 220.0, 247.1,
        261.6, 293.6, 329.6, 349.0, 392.0, 440.0, 494.0,
        523.2, 587.2, 659.2, 698.3, 784.0, 880.0, 988.0,
        1046.4, 1174.4, 1318.4, 1396.8, 1567.7, 1760.0, 1975.3};

        /******************************************************************************************************
        PITCH[ ]:指的是 音高,對(duì)應(yīng)上圖中的按鍵號(hào)
        例:中音 do:如圖對(duì)應(yīng) 8 號(hào)鍵
        高音 do:如圖對(duì)應(yīng) 15 號(hào)鍵
        好處:假如歌曲播放到了第 i 個(gè)音,那么 PITCH[i] 就是對(duì)應(yīng)鋼琴上的按鍵
        那么 PIANO_F[ PITCH[i] ] 就是對(duì)應(yīng)的琴鍵的頻率,方便編程使用
        注:255 代表 音樂(lè)結(jié)束
        0 代表 八分休止符
        ******************************************************************************************************/

        unsigned char codePITCH[ ] = {16, 17, 16, 15, 16, 12, 17, 16, 15,
        16, 17, 16, 15, 15, 19, 16,
        16, 17, 16, 15, 16, 12, 17, 16, 15,
        16, 17, 16, 15, 15, 12,
        12, 10, 12, 15, 15,
        16, 16, 16, 17, 17, 12,
        12, 10, 12, 0, 15, 15, 16,
        16, 16, 16, 19, 17, 12,
        12, 10, 0, 12, 0, 15, 15, 15,
        16, 16, 16, 17, 17, 12,
        12, 10, 0, 12, 0, 15, 15, 16,
        16, 16, 16, 19, 17, 26,
        26, 24, 0, 26, 26, 22, 0, 23,
        23, 22, 23, 0, 24, 23, 24, 26,
        26, 24, 0, 26, 26, 22, 0, 23,
        23, 22, 0, 23, 22,
        255};

        /***************************************************************************************************************
        BEAT[ ]:指的是 節(jié)拍,數(shù)值代表基本節(jié)拍的倍數(shù),這里基本節(jié)拍為 十六分音符 長(zhǎng)
        例:8,代表 8 倍 十六分音符 長(zhǎng),即:二分音符
        4,代表 4 倍 十六分音符 長(zhǎng),即:四分音符
        2,代表 2 倍 十六分音符 長(zhǎng),即:八分音符
        1,代表 1 倍 十六分音符 長(zhǎng),即:十六分音符
        6,代表 6 倍 十六分音符 長(zhǎng),即:符點(diǎn)四分音符
        ***************************************************************************************************************/

        unsigned char codeBEAT[ ] = {4, 1, 1, 2, 2, 2, 1, 1, 2, 4, 1, 1, 2, 2, 2, 4,
        4, 1, 1, 2, 2, 2, 1, 1, 2, 4, 1, 1, 2, 6, 2,
        2, 4, 2, 6, 2, 2, 2, 2, 2, 6, 2,
        2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8,
        255};

        unsigned chartime_h = 0;// 用于向定時(shí)器中斷程序傳遞下一步定時(shí)信息
        unsigned chartime_l = 0;

        unsigned inttime = 0;// 根據(jù)按鍵頻率,換算出應(yīng)該定時(shí)多長(zhǎng)時(shí)間
        unsigned chari;

        voidInit_Timer0(void);// 初始化 定時(shí)器 0
        voidDelay(unsigned intt);// 普通延時(shí)
        voidDelay_ms(unsigned intt);// 相當(dāng)近似的延遲 t ms

        voidmain (void)
        {
        Init_Timer0();

        for(i = 0; PITCH[i] != 255; i++) {// 順序播放,255 為音樂(lè)結(jié)束

        TR0 = 0;// 關(guān) 定時(shí)器0

        Delay_ms(20);// 延時(shí)一段時(shí)間,保證按鍵與按鍵之間能分得清楚

        /*********************************************************************************************************************
        定時(shí)時(shí)間 time 的計(jì)算:

        以 中央 C 為例:頻率為 261.6 Hz,就是每秒 261.6 下,倒數(shù)就是 每下 1/261.6 s,
        換成 us 就是 1,000,000/261.6,每響一次是一個(gè)上升沿加一個(gè)下降沿,
        因此,變換的次數(shù)應(yīng)該是 2 倍,每次變換所花時(shí)間是一半,
        即:1,000,000/(2*261.6)
        **********************************************************************************************************************/

        time = (unsigned int)(1000000 / (2 * PIANO_F[PITCH[i]]));

        time_h = (65536 - time) / 256;
        time_l = (65536 - time) % 256;

        TH0 = time_h;// 定時(shí)器賦值
        TL0 = time_l;

        TR0 = 1;// 開(kāi) 定時(shí)器0

        /****************************************************************************************************************
        如果音高是 0,說(shuō)明是 八分休止符,關(guān)定時(shí)器,定時(shí)器不驅(qū)動(dòng)喇叭,也就沒(méi)有聲音了
        ****************************************************************************************************************/

        if(PITCH[i] == 0) TR0 = 0;

        /********************************************************************************************************
        相當(dāng)重要的延時(shí)!節(jié)拍全部由它控制,不是很精確,其實(shí)用 定時(shí)器 1 可能更好
        ********************************************************************************************************/

        Delay_ms(BEAT[i] * 30);
        }

        TR0 = 0;// 音樂(lè)播放完后,關(guān)定時(shí)器,收尾

        /*****************************************************************************************************************
        相當(dāng)重要!沒(méi)有此語(yǔ)句將導(dǎo)致循環(huán)執(zhí)行 main 函數(shù)!

        詳細(xì)討論參見(jiàn):http://gaebolg.blog.163.com/blog/static/19826906820122254823928/
        *****************************************************************************************************************/

        while(1);
        }

        voidInit_Timer0(void)
        {
        TMOD = 0x01;// 定時(shí)器 0,模式1
        EA = 1;// 開(kāi) 總中斷
        ET0 = 1;// 開(kāi) 定時(shí)器 0 中斷
        }

        voidTimer0_ISR(void)interrupt1
        {
        TH0 = time_h;// 重裝初值
        TL0 = time_l;

        SPK = !SPK;// 產(chǎn)生方波,驅(qū)動(dòng)喇叭發(fā)聲
        }

        voidDelay(unsigned intt)
        {
        while(t--);
        }

        voidDelay_ms(unsigned intt)// 根據(jù)測(cè)試,可以相當(dāng)近似的表示 t ms
        {
        while(t--) {
        Delay(245);
        Delay(245);
        }
        }



        關(guān)鍵詞: C51喇叭播

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 周口市| 丁青县| 汶上县| 夏津县| 七台河市| 达日县| 海盐县| 潜山县| 潼关县| 富裕县| 武义县| 崇义县| 霍山县| 五莲县| 两当县| 道孚县| 隆安县| 栾川县| 益阳市| 潜山县| 泊头市| 乌什县| 松滋市| 沙洋县| 都安| 腾冲县| 南靖县| 灵寿县| 那曲县| 同江市| 炉霍县| 山东| 鸡西市| 威远县| 裕民县| 四平市| 玉山县| 枝江市| 自治县| 香格里拉县| 丰都县|