找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

單片機音樂計時器Proteus仿真+代碼設(shè)計分享

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:368262 發(fā)表于 2019-6-20 15:53 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)

要求通過4個按鍵來設(shè)置想要倒數(shù)的時間,其中系統(tǒng)默認(rèn)倒計時為1分鐘,K1可調(diào)整倒計時間1~60分鐘,K2可設(shè)置倒計時為5分鐘,K3可設(shè)置倒計時為15分鐘,K4可設(shè)置的倒計時為20分鐘,K5為啟動鍵。當(dāng)初值被設(shè)定好,只要啟動K5,就可以啟動倒計時功能。當(dāng)計時為0時播放音樂,而且它能循環(huán)播放,可隨時人為停止。
二. 方案原理
此次設(shè)計以89C52芯片為核心來設(shè)計音樂計時器,其具有倒數(shù)計時、時間設(shè)置、音樂演奏等功能。除了設(shè)定默認(rèn)值為1分鐘外,本計時器還有5分鐘,15分鐘和20分鐘的快捷鍵,而且可在上述時間的基礎(chǔ)上任意調(diào)整自己想設(shè)定的倒計時時間。當(dāng)?shù)褂嫊r結(jié)束時,計時器會播放音樂,可循環(huán)播放,亦可隨時停止。
  這個音樂計時器由四個模塊組成,分別是數(shù)碼管模塊,倒計時模塊,音樂模塊和核心處理模塊。通過對P2口的查詢,我們可以實現(xiàn)對時間的不同設(shè)定和調(diào)整。系統(tǒng)晶振為12MHz,RESET管腳處連接復(fù)位開關(guān)。同時,我們使用查詢方式來設(shè)定定時器時間。
三. 方案具體說明
通過計算某一音頻周期(1/頻率),然后將此周期除以2,即為半周期的時間。利用單片機定時器計時這個半周期時間,每當(dāng)計時到后就將輸出脈沖的I/O口反相,然后重復(fù)計時此半周期時間再對I/O口反相,這樣就能在此I/O口上得到此頻率的脈沖,再結(jié)合中斷延時程序,程序中節(jié)拍控制是通過調(diào)用延時子程序DELAY的次數(shù)來實現(xiàn),產(chǎn)生音樂。利用P2.1、P2.2、P2.3管腳,對應(yīng)開關(guān)K2、K3、K4,分別啟動不同的倒計時程序5分鐘、15分鐘、20分鐘。通過查詢方式對P3.2管腳進(jìn)行查詢,進(jìn)入1到60分鐘的時間調(diào)整程序。P0引腳作為顯示輸出連至LED顯示器,P1.0、P1.1、P1.2、P1.3為位選信號,控制不同位的數(shù)碼管。程序中使用定時器T0方式1來產(chǎn)生歌譜中各音符對應(yīng)頻率的音頻脈沖,由P1.5通放大輸出,,1拍為748 ms。確定了設(shè)計思路后,就可以具體設(shè)計了。先編寫程序,然后加入硬件進(jìn)行調(diào)試。
四. 模塊原理說明
(一).數(shù)碼管模塊
     數(shù)碼管動態(tài)顯示接口是單片機中應(yīng)用最為廣泛的一種顯示方式之一,動態(tài)驅(qū)動是將所有數(shù)碼管的8個顯示筆劃"a,b,c,d,e,f,g,dp"的同名端連在一起,另外為每個數(shù)碼管的公共極COM增加位選通控制電路,位選通由各自獨立的I/O線控制,當(dāng)單片機輸出字形碼時,所有數(shù)碼管都接收到相同的字形碼,但究竟是那個數(shù)碼管會顯示出字形,取決于單片機對位選通COM端電路的控制,所以我們只要將需要顯示的數(shù)碼管的選通控制打開,該位就顯示出字形,沒有選通的數(shù)碼管就不會亮。通過分時輪流控制各個數(shù)碼管的的COM端,就使各個數(shù)碼管輪流受控顯示,這就是動態(tài)驅(qū)動。在輪流顯示過程中,每位數(shù)碼管的點亮?xí)r間為1~2ms,由于人的視覺暫留現(xiàn)象及發(fā)光二極管的余輝效應(yīng),盡管實際上各位數(shù)碼管并非同時點亮,但只要掃描的速度足夠快,給人的印象就是一組穩(wěn)定的顯示數(shù)據(jù),不會有閃爍感,動態(tài)顯示的效果和靜態(tài)顯示是一樣的,能夠節(jié)省大量的I/O端口,而且功耗更低。
(二).倒計時模塊
     定時器倒計時部分用中斷來實現(xiàn)功能。定義定時器0,工作方式1,當(dāng)時間過去1s后,數(shù)碼管就按照設(shè)定規(guī)則顯示數(shù)字。
(三).音樂模塊
(1) 音樂的產(chǎn)生主要是通過單片機的I/O口輸出高低不同的脈沖信號來控制蜂鳴器發(fā)音。要想產(chǎn)生音頻脈沖信號,需要算出某一音頻的周期(1/頻率),然后將此周期除以2,即為半周期的時間。利用單片機定時器計時這個半個周期時間,每當(dāng)計時到后就將輸出脈沖的I/O口反相,然后重復(fù)計時此半周期時間再對I/O口反相,這樣就能在此I/O口上得到此頻率的脈沖。
通常,利用單片機的內(nèi)部定時器0,工作在方式1下,改變計數(shù)初值TH0和TL0來產(chǎn)生不同頻率。 對于音樂的節(jié)拍,每個音符使用1個字節(jié),字節(jié)的高4位代表音符的高低,低4位代表音符的節(jié)拍。如果1拍為0.4S,1/4拍為0.1S,只要設(shè)定延遲時間就可求得節(jié)拍的時間。假設(shè)1/4拍為1DELAY,那么1拍應(yīng)為4DELAY,以此類推。所以只要求得1/4拍的DELAY,其余的節(jié)拍就是它的倍數(shù)。
總而言之,一首樂曲是由音階和節(jié)拍兩大要素構(gòu)成。一首樂曲演奏的原理是:不同音階分別對應(yīng)不同的頻率,發(fā)出不同的音調(diào),而節(jié)拍則控制發(fā)出音調(diào)時間的長短;若將樂曲的音調(diào)連續(xù)發(fā)出,并使其按相應(yīng)的節(jié)拍變化,即可演奏一首樂曲。根據(jù)這一特點,我們采用單片機輔以相應(yīng)的接口來設(shè)計音樂播放器。
(2)產(chǎn)生音樂通過單片機的I/O口輸出高低不同的脈沖信號來控制蜂鳴器發(fā)音。利用AT89C52單片機的內(nèi)部定時器0,工作在方式1下,改變計數(shù)初值TH0和TL0來產(chǎn)生不同的頻率。若單片機采用12MHz晶振,要產(chǎn)生頻率為587Hz的音頻脈沖時,其音頻脈沖信號的周期T=1/587=1703.577us,約1704us,半周期的時間852us,因此只要今計數(shù)器計數(shù)=852us/1us=852,在每計數(shù)852次時將I/O口反相,就可得C調(diào)中音Re。  
計數(shù)脈沖值與頻率的關(guān)系如下:      
N=Fi/2/Fr 式中:N—計數(shù)值     
Fi—機器頻率。晶體振蕩器為12MHz時,內(nèi)部計時一次為1us,故其頻率為1MHz      
Fr—想要產(chǎn)生的頻率  所以定時常數(shù)(計數(shù)值T)的求法:     T=65536-N=65536-Fi/2/Fr  例如,設(shè)Fi=1MHz,求低音Do(262Hz)、中音Do(523Hz)和高音Do(1046Hz)的計數(shù)初值。  
解:T=65536-N=65536-Fi/2/Fr=65536-500000/Fr      
低音Do的T=65536-500000/262=63628      
中音Do的T=65536-500000/523=64580      
高音Do的T=65536-500000/1046=65058
(四).核心處理模塊
    對計時器和中斷進(jìn)行初始化后,系統(tǒng)出現(xiàn)默認(rèn)時間設(shè)定值,也就是1分鐘。如果有按鍵按下,屏幕上面的時間會發(fā)生改變。K1可調(diào)整倒計時間1~60分鐘,K2可設(shè)置倒計時為5分鐘,K3可設(shè)置倒計時為15分鐘,K4可設(shè)置的倒計時為20分鐘。在時間設(shè)定完畢后,利用K5啟動計時器,在計時結(jié)束后調(diào)用音樂函數(shù),SPEAKER就會播放出我們所設(shè)定的旋律。
五. 實驗原理圖
六. 實驗感悟
在本次設(shè)計中,我重新復(fù)習(xí)了中斷和計時器部分的知識,同時也學(xué)到了單片機播放音樂的原理。然而在實驗過程中,我遇到了不少問題:1.復(fù)位開關(guān)失效,即它并未有起到復(fù)位效果;2.每次設(shè)定好初始值后,計時器往往會自動啟動計時功能,即K5失效;3.K5按鍵不靈敏,往往需要重復(fù)按2次以上才會啟動計時;4.SPEAKER并沒有按照程序的設(shè)定播放出一段完整的音樂。如今,通過調(diào)試和修改,一到三的問題得到了解決,而第四個問題,只有在對程序進(jìn)行編譯,才能發(fā)現(xiàn)錯誤的所在。在整個實驗過程中,我在不斷的修改與調(diào)整中學(xué)習(xí)到越來越多的東西,同時也讓我原本掌握的知識更加牢固,這對我來說是大有裨益的。
七. 相關(guān)程序
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit SPK=P1^5;
sbit K1=P2^0;
sbit K2=P2^1;
sbit K3=P2^2;
sbit K4=P2^3;
sbit K5=P2^4;
sbit A1=P1^0;
sbit A2=P1^1;
sbit A3=P1^2;
sbit A4=P1^3;
uchar miao_g,miao_d,fen_g,fen_d;
uchar code Num[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar num1;
uchar code song[]={0x58,0x84,0xA8,0x84,0x68,0x82,0x62,0x5C,0xA4,0xA4,0xA4,0xA4,0x93,0x81,0x9C,0x9C,0xC8,0xC4,0xC8,0xD2,0xC2,0xA8,0x92,0x82,0x6B,0xC4,0xC4,0xC4,0xA8,0x94,0x8C,0xFF};
//音律部分,前四位為音階,后四位為節(jié)拍,其中以1/4節(jié)拍為單位節(jié)拍;
uchar m;
uchar code yinjie[]={0xff,0xff,0xFC,0x4A,0xFC,0xAE,0xFD,0x08,0xFD,0x30,0xFD,0x80,0xFD,0xC6,0xFE,0x02,0xFE,0x2A,0xFE,0x5C,0xFE,0x84,0xFE,0x98,0xFE,0xC0,0xFE,0xE8,0xFF,0x06};
//音階所對應(yīng)的計時器初值,前兩位是占位,中間14位是中音1~7,后面14位是高音1~7,晶振為12MHz;
uchar ding;
void delay_1();//1/4節(jié)拍函數(shù)聲明;
void delay(uint k);//計數(shù)器延時函數(shù)聲明;
void display(uint fen_g,uint fen_d,uint miao_g,uint miao_d);//數(shù)碼管顯示函數(shù)聲明;
void music();//音樂函數(shù)聲明;
void delayxiaodou(int n);//消抖函數(shù)聲明,用于主函數(shù)K5;
//數(shù)碼管部分
void delay(uint k)          //延時函數(shù),用于計時器計算1s部分和數(shù)碼管延時顯示部分
{  uint x,y;
    for(x=k;x>0;x--)
           for(y=125;y>0;y--);
           }         
void delayxiaodou(int n)
{
     while(n--);
}
void display(uint fen_g,uint fen_d,uint miao_g,uint miao_d)   //數(shù)碼管顯示時間
{   
  
            P0=0xFF;                 //消隱;
     A1=1;A2=0;A3=0;A4=0;
         P0=Num[fen_g];
         delay(1);
         P0=0xFF;
         A1=0;A2=1;A3=0;A4=0;
         P0=Num[fen_d];
         delay(1);
         A1=0;A2=0;A3=1;A4=0;
         P0=0xFF;
         P0=Num[miao_g];
         delay(1);
         A1=0;A2=0;A3=0;A4=1;
         P0=0xFF;
         P0=Num[miao_d];
         delay(1);
         TR0=0;
         
}
//倒計時部分
void timer()interrupt 1        //定時器0,方式1
{
   TH0=0x3C;  //50ms倒計時
   TL0=0xB0;
   num1++;
   if(num1==20) //50ms*20=1s
   {   num1=0;
       miao_d--;
           if(miao_d==-1)
           {   miao_d=9;
               miao_g--;
                   if(miao_g==-1)
                   {  miao_g=5;
                      fen_d--;
                          if(fen_d==-1)
                          {  fen_d=9;
                             fen_g--;
                                 if(fen_g==-1)
                                 {
                                    fen_g=5;}}}}}}
//音樂部分
void music()
{  uint data j=0;
    uchar data g;
        uchar data i;
        while (*(song+j)!=0xff)//歌曲的停頓;
        {   g=*(song+j)&0x0F;//低4位,節(jié)拍;
            m=*(song+j)>>4;         //高4位,音階;
                TH1=yinjie[2*m];
                TL1=yinjie[2*m+1];
                TR1=1;
                if((yinjie[2*m]==0xff)&&(yinjie[2*m+1]==0xff))
                {  TR1=0;
                   SPK=1;}
                for(i=g;i>0;i--)
                {  delay_1();
                   TR1=0;
                   j++;
                   }}}                                                  
void delay_1()//1/4        節(jié)拍所需要用的時間,約187ms;
{  uchar m,n,p;
   for(m=100;m>0;m--)
     for(n=20;n>0;n--)
           for(p=15;p>0;p--);
}
void timer0() interrupt 3        //半個周期后,SPK處的脈沖反相,得到音階;
{ TH1=yinjie[2*m];
  TL1=yinjie[2*m+1];
  SPK=!SPK;
  }
//核心處理模塊
void main()
{
   TMOD=0x01; //啟動定時器,初值為50ms;
   TH0=0x3C;
   TL0=0xB0;
   ET0=1;     //定義中斷;
   ET1=1;
   EA=1;
   TR0=0;          //時鐘初始化;
   miao_g=miao_d=fen_g=0;
   fen_d=1;
   ding=0;
   while(1)
   {
      display(fen_g,fen_d,miao_g,miao_d);
          if(K5!=0)
          {
          if(K1==0)                   //K1按鍵:在1分鐘基礎(chǔ)上遞增,可自定義計時時間;
           {  delayxiaodou(100);
              if(K1==0)
                  { miao_g=miao_d=0;
                    fen_d++;
                        if(fen_d==10)
                        {  fen_d=0;
                           fen_g++;
                           if(fen_g==6)
                           {fen_d=0;
                           }}}}
                           while(!K1);
          if(K2==0)                        //K2按鍵:初值為5分鐘;
           {  delayxiaodou(100);
               if(K2==0)
                   {  
                      miao_g=miao_d=0;
                      fen_d=5;
                          fen_g=0;
               
                          }
                          }
                          while(!K2);
          if(K3==0)                        //K3按鍵:初值為15分鐘;
            {  delayxiaodou(100);
                   if(K3==0)
                   { miao_g=miao_d=0;
                     fen_d=5;
                         fen_g=1;
                        
                         }
                         }
                         while(!K3);
                if(K4==0)                 //K4按鍵:初值為20分鐘;
                {  delayxiaodou(100);
                   if(K4==0)
                   {  miao_g=miao_d=0;
                      fen_d=0;
                          fen_g=2;
                          
                          }
                          }
                          while(!K4);
                          }
                if(K5==0)                  //K5按鍵:初值設(shè)定好后,啟動倒計時;
                 {  delayxiaodou(1);
                    if(K5==0)
                        {  ding++;
                           if(ding==2)
                           { ding=5;}
                           }}
                           while(!K5);
                   if(ding==5)
                        TR0=1;
                                 //倒計時結(jié)束;
                        display(fen_g,fen_d,miao_g,miao_d);
                        if(fen_g==0&&fen_d==0&&miao_g==0&&miao_d==0)
                          music();
        }
        }
  
全部資料51hei下載地址:
單片機設(shè)計——音樂計時器.zip (472.64 KB, 下載次數(shù): 105)
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂2 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:626741 發(fā)表于 2019-10-19 19:48 | 只看該作者
portues 工程文件是哪個呀?下載之后,沒有找到
后來才知道原來需要安裝Proteus7.5才能打開,下面是仿真圖

51hei.png (18.19 KB, 下載次數(shù): 100)

51hei.png
回復(fù)

使用道具 舉報

板凳
ID:626741 發(fā)表于 2019-10-19 19:57 | 只看該作者
請問壓縮包里的protues工程文件在哪里呀 沒有找到
回復(fù)

使用道具 舉報

地板
ID:462085 發(fā)表于 2020-3-6 16:56 | 只看該作者
不錯的設(shè)計,值得學(xué)習(xí)
回復(fù)

使用道具 舉報

5#
ID:341891 發(fā)表于 2020-5-29 18:45 | 只看該作者
好東西 謝謝樓主
回復(fù)

使用道具 舉報

6#
ID:781587 發(fā)表于 2020-6-20 19:45 | 只看該作者
為啥數(shù)碼管一閃一閃的,除了復(fù)位和K5能按,其它按鈕都按不了,小白的我太難了
回復(fù)

使用道具 舉報

7#
ID:910064 發(fā)表于 2021-4-26 16:49 | 只看該作者
羽兒 發(fā)表于 2020-6-20 19:45
為啥數(shù)碼管一閃一閃的,除了復(fù)位和K5能按,其它按鈕都按不了,小白的我太難了

哇,我也是嗚嗚嗚,那你現(xiàn)在解決了嗎
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

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

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