找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2725|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

51單片機用定時器T0的模式0控制播放《好人一生平安》

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:223935 發(fā)表于 2017-8-1 20:44 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式



C音調(diào)與譜曲控制對應(yīng)表
音調(diào)   低1(低音“dao”)  低2  低3  低4  低5  低6  低7  

頻率   262                 294  330  349  392  440  494

音調(diào)   中1(中音“dao”)  中2  中3  中4  中5  中6  中7

頻率   523                 587  659  698  784  880  988

音調(diào)   高1(高音“dao”)  高2  高3  高4  高5  高6  高7

頻率   1046                1175 1318 1397 1568 1760 1967


實現(xiàn)方法

1.音頻控制

要讓蜂鳴器發(fā)出某音調(diào)的聲音,只要給蜂鳴器輸送該音調(diào)頻率的電平信號就可以了。
由于單片機I/O口的輸出只有高電平“1”和低電平“0”兩種狀態(tài),因此給蜂鳴器輸送的電平信號實際上就是該音頻的方波。
例如:中音“1”的頻率為523HZ,它的周期為1/523s,即1.91ms,因此,只要給蜂鳴器輸送周期為1.91ms的脈沖方波電平信號就能發(fā)出
523HZ的音調(diào),該方波的半周期為1.91/2=0.955ms.為此,需要利用定時器的中斷,讓輸送給蜂鳴器的電平信號每0.995ms取反一次即可,
單片機晶振頻率為11.0952MHZ,它的一個機器周期為12*(1/11.0592)us,所以需要的機器周期總數(shù)為

                                                955us/1.085us=880

即定時器的定時常數(shù)應(yīng)取為880,由上述分析,發(fā)出頻率為f的音頻時,定時常數(shù)C計算公式為

                                                C=(10^6 / 2f)/1.085us =  460830/f

因為T0工作方式0,其最大計數(shù)值為8192,完全可以滿足各音頻定時常數(shù)設(shè)置的需要?梢宰C明,在已知定時常數(shù)C的條件下,13位計數(shù)器
的高8位和低5位的初值可由以下公式設(shè)定:

                    TH0=(8192-C)/32   //13位計數(shù)器高8位的賦初值方法
                    TL0=(8192-C)%32   //13位計數(shù)器低5位的賦初值方法


2.節(jié)拍控制

每分鐘72拍,每個節(jié)拍所需時間:(1000*60/72)ms=833ms     // 具體見單片機扉頁

3.音調(diào)與節(jié)拍的存儲

可以將簡譜中所有音調(diào)的頻率及節(jié)拍分別存儲于兩個數(shù)組,然后依次從數(shù)組中讀出頻率,再根據(jù)頻率和定時器延時常數(shù)的計算公式
即可由定時器中斷控制發(fā)出該音調(diào)的音頻,其發(fā)聲時間可由節(jié)拍控制(1-4個延時單位)。

4.音調(diào)的宏定義

直接將頻率存入數(shù)組,顯然不如以“dao,rei,mi,fa,sao……”的形式存儲方便,但是為了讓單片機認(rèn)識這些,需要在程序開頭處對各音調(diào)
的頻率進行宏定義。例如,低音6的頻率為440Hz,中音6的頻率為880Hz,高音6的頻率為1760Hz。所以可以對這三個頻率進行如下宏定義


           #define l_la 440  //將“l(fā)_la”宏定義為低音“6”的頻率440Hz,以此類推
           #define la 880
           #define h_la 1760


程序設(shè)計

#include<reg52.h>
sbit deep=P2^3;
uint C;
#define uint unsigned int
#define uchar unsigned char
#define l_dao 262
#define l_re 286
#define l_mi 311
#define l_fa 349
#define l_sao 392
#define l_la 440
#define l_xi 494
#define dao 523
#define re 587
#define mi 659
#define fa 698
#define sao 784
#define la 880
#define xi 987
#define h_dao 1046
#define h_re 1174
#define h_mi 1318
#define h_fa 1396
#define h_sao 1567
#define h_la 1760
#define h_xi 1975

void delay(uint xms)
{
    uchar i,j;
    for(i=xms;i>0;i--)
       for(j=110;j>0;j--);
}


void main()
{
    uchar i.j;
    uint code f[]={re,mi,re,dao,l_la,dao,l_la,
                   l_sao,l_mi,l_sao,l_la,dao,
                   l_la,dao,sao,la,mi,sao,re,mi,re,mi,sao,mi,
                   l_sao,l_mi,l_sao,l_la,dao,
                   l_la,l_la,dao,l_la,l_sao,l_re,l_mi,
                   l_sao,re,re,sao,la,sao,
                   fa,mi,sao,mi,la,sao,mi,re,mi,l_la,dao,
                   re,mi,re,mi,sao,mi,l_sao,l_mi,l_sao,l_la,dao,
                   l_la,dao,re,l_la,dao,re,mi,re,l_la,dao,re,l_la,dao,
                   re,mi,re,l_la,dao,re,l_la,dao,re,mi,re,0xff};

    uchar code JP[]={4,1,1,4,1,1,2,           //每行對應(yīng)一小節(jié)音調(diào)的節(jié)拍
                     2,2,2,2,8,
                         4,2,3,1,2,2,
                       10,
                      4,2,2,4,4,
                      2,2,2,2,4,
                   2,2,2,2,2,2,2,
                       10,
                      4,4,4,2,2,
                      4,2,4,4,
                      4,2,2,2,2,2,2,
                        10,
                      4,2,2,4,4,
                      2,2,2,2,6,
                      4,2,2,4,1,1,4,
                        10,
                      4,2,2,4,1,1,4,
                         10};


      EA=1;               //開總中斷
      ET0=1;              //定時器T0中斷允許
      TMOD=0X00;          //使用定時器T0的模式0(13位計數(shù)器)
      while(1)            //無限循環(huán)
       {
           i=0;
           while(1)
           {
              i=0;                     //從第一個音調(diào)f[0]開始播放
              while(f[i]!=0xff)        //只要沒有讀到結(jié)束標(biāo)志就繼續(xù)播放  
                  {
                      C=460830/f[i];
                      TH0=(8192-C)/32;   
                      TL0=(8192-C)%32;
                      TR0=1;
                      for(j=0;j<JP[i];j++)  //控制節(jié)拍數(shù)
                      delay();              //延時一個節(jié)拍單位
                       TR0=0;              //關(guān)閉定時器T0
                        i++;               //播放下一個音調(diào)
                   }
            }
}


void Time() interrupt 1
{
        deep=!deep;
        TH0=(8192-C)/32;
        TL0=(8192-C)%32;
}

















































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

使用道具 舉報

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

本版積分規(guī)則

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

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

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