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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

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

[復制鏈接]
跳轉到指定樓層
樓主
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)

要求通過4個按鍵來設置想要倒數的時間,其中系統默認倒計時為1分鐘,K1可調整倒計時間1~60分鐘,K2可設置倒計時為5分鐘,K3可設置倒計時為15分鐘,K4可設置的倒計時為20分鐘,K5為啟動鍵。當初值被設定好,只要啟動K5,就可以啟動倒計時功能。當計時為0時播放音樂,而且它能循環播放,可隨時人為停止。
二. 方案原理
此次設計以89C52芯片為核心來設計音樂計時器,其具有倒數計時、時間設置、音樂演奏等功能。除了設定默認值為1分鐘外,本計時器還有5分鐘,15分鐘和20分鐘的快捷鍵,而且可在上述時間的基礎上任意調整自己想設定的倒計時時間。當倒計時結束時,計時器會播放音樂,可循環播放,亦可隨時停止。
  這個音樂計時器由四個模塊組成,分別是數碼管模塊,倒計時模塊,音樂模塊和核心處理模塊。通過對P2口的查詢,我們可以實現對時間的不同設定和調整。系統晶振為12MHz,RESET管腳處連接復位開關。同時,我們使用查詢方式來設定定時器時間。
三. 方案具體說明
通過計算某一音頻周期(1/頻率),然后將此周期除以2,即為半周期的時間。利用單片機定時器計時這個半周期時間,每當計時到后就將輸出脈沖的I/O口反相,然后重復計時此半周期時間再對I/O口反相,這樣就能在此I/O口上得到此頻率的脈沖,再結合中斷延時程序,程序中節拍控制是通過調用延時子程序DELAY的次數來實現,產生音樂。利用P2.1、P2.2、P2.3管腳,對應開關K2、K3、K4,分別啟動不同的倒計時程序5分鐘、15分鐘、20分鐘。通過查詢方式對P3.2管腳進行查詢,進入1到60分鐘的時間調整程序。P0引腳作為顯示輸出連至LED顯示器,P1.0、P1.1、P1.2、P1.3為位選信號,控制不同位的數碼管。程序中使用定時器T0方式1來產生歌譜中各音符對應頻率的音頻脈沖,由P1.5通放大輸出,,1拍為748 ms。確定了設計思路后,就可以具體設計了。先編寫程序,然后加入硬件進行調試。
四. 模塊原理說明
(一).數碼管模塊
     數碼管動態顯示接口是單片機中應用最為廣泛的一種顯示方式之一,動態驅動是將所有數碼管的8個顯示筆劃"a,b,c,d,e,f,g,dp"的同名端連在一起,另外為每個數碼管的公共極COM增加位選通控制電路,位選通由各自獨立的I/O線控制,當單片機輸出字形碼時,所有數碼管都接收到相同的字形碼,但究竟是那個數碼管會顯示出字形,取決于單片機對位選通COM端電路的控制,所以我們只要將需要顯示的數碼管的選通控制打開,該位就顯示出字形,沒有選通的數碼管就不會亮。通過分時輪流控制各個數碼管的的COM端,就使各個數碼管輪流受控顯示,這就是動態驅動。在輪流顯示過程中,每位數碼管的點亮時間為1~2ms,由于人的視覺暫留現象及發光二極管的余輝效應,盡管實際上各位數碼管并非同時點亮,但只要掃描的速度足夠快,給人的印象就是一組穩定的顯示數據,不會有閃爍感,動態顯示的效果和靜態顯示是一樣的,能夠節省大量的I/O端口,而且功耗更低。
(二).倒計時模塊
     定時器倒計時部分用中斷來實現功能。定義定時器0,工作方式1,當時間過去1s后,數碼管就按照設定規則顯示數字。
(三).音樂模塊
(1) 音樂的產生主要是通過單片機的I/O口輸出高低不同的脈沖信號來控制蜂鳴器發音。要想產生音頻脈沖信號,需要算出某一音頻的周期(1/頻率),然后將此周期除以2,即為半周期的時間。利用單片機定時器計時這個半個周期時間,每當計時到后就將輸出脈沖的I/O口反相,然后重復計時此半周期時間再對I/O口反相,這樣就能在此I/O口上得到此頻率的脈沖。
通常,利用單片機的內部定時器0,工作在方式1下,改變計數初值TH0和TL0來產生不同頻率。 對于音樂的節拍,每個音符使用1個字節,字節的高4位代表音符的高低,低4位代表音符的節拍。如果1拍為0.4S,1/4拍為0.1S,只要設定延遲時間就可求得節拍的時間。假設1/4拍為1DELAY,那么1拍應為4DELAY,以此類推。所以只要求得1/4拍的DELAY,其余的節拍就是它的倍數。
總而言之,一首樂曲是由音階和節拍兩大要素構成。一首樂曲演奏的原理是:不同音階分別對應不同的頻率,發出不同的音調,而節拍則控制發出音調時間的長短;若將樂曲的音調連續發出,并使其按相應的節拍變化,即可演奏一首樂曲。根據這一特點,我們采用單片機輔以相應的接口來設計音樂播放器。
(2)產生音樂通過單片機的I/O口輸出高低不同的脈沖信號來控制蜂鳴器發音。利用AT89C52單片機的內部定時器0,工作在方式1下,改變計數初值TH0和TL0來產生不同的頻率。若單片機采用12MHz晶振,要產生頻率為587Hz的音頻脈沖時,其音頻脈沖信號的周期T=1/587=1703.577us,約1704us,半周期的時間852us,因此只要今計數器計數=852us/1us=852,在每計數852次時將I/O口反相,就可得C調中音Re。  
計數脈沖值與頻率的關系如下:      
N=Fi/2/Fr 式中:N—計數值     
Fi—機器頻率。晶體振蕩器為12MHz時,內部計時一次為1us,故其頻率為1MHz      
Fr—想要產生的頻率  所以定時常數(計數值T)的求法:     T=65536-N=65536-Fi/2/Fr  例如,設Fi=1MHz,求低音Do(262Hz)、中音Do(523Hz)和高音Do(1046Hz)的計數初值。  
解: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
(四).核心處理模塊
    對計時器和中斷進行初始化后,系統出現默認時間設定值,也就是1分鐘。如果有按鍵按下,屏幕上面的時間會發生改變。K1可調整倒計時間1~60分鐘,K2可設置倒計時為5分鐘,K3可設置倒計時為15分鐘,K4可設置的倒計時為20分鐘。在時間設定完畢后,利用K5啟動計時器,在計時結束后調用音樂函數,SPEAKER就會播放出我們所設定的旋律。
五. 實驗原理圖
六. 實驗感悟
在本次設計中,我重新復習了中斷和計時器部分的知識,同時也學到了單片機播放音樂的原理。然而在實驗過程中,我遇到了不少問題:1.復位開關失效,即它并未有起到復位效果;2.每次設定好初始值后,計時器往往會自動啟動計時功能,即K5失效;3.K5按鍵不靈敏,往往需要重復按2次以上才會啟動計時;4.SPEAKER并沒有按照程序的設定播放出一段完整的音樂。如今,通過調試和修改,一到三的問題得到了解決,而第四個問題,只有在對程序進行編譯,才能發現錯誤的所在。在整個實驗過程中,我在不斷的修改與調整中學習到越來越多的東西,同時也讓我原本掌握的知識更加牢固,這對我來說是大有裨益的。
七. 相關程序
#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};
//音律部分,前四位為音階,后四位為節拍,其中以1/4節拍為單位節拍;
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};
//音階所對應的計時器初值,前兩位是占位,中間14位是中音1~7,后面14位是高音1~7,晶振為12MHz;
uchar ding;
void delay_1();//1/4節拍函數聲明;
void delay(uint k);//計數器延時函數聲明;
void display(uint fen_g,uint fen_d,uint miao_g,uint miao_d);//數碼管顯示函數聲明;
void music();//音樂函數聲明;
void delayxiaodou(int n);//消抖函數聲明,用于主函數K5;
//數碼管部分
void delay(uint k)          //延時函數,用于計時器計算1s部分和數碼管延時顯示部分
{  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)   //數碼管顯示時間
{   
  
            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位,節拍;
            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        節拍所需要用的時間,約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分鐘基礎上遞增,可自定義計時時間;
           {  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按鍵:初值設定好后,啟動倒計時;
                 {  delayxiaodou(1);
                    if(K5==0)
                        {  ding++;
                           if(ding==2)
                           { ding=5;}
                           }}
                           while(!K5);
                   if(ding==5)
                        TR0=1;
                                 //倒計時結束;
                        display(fen_g,fen_d,miao_g,miao_d);
                        if(fen_g==0&&fen_d==0&&miao_g==0&&miao_d==0)
                          music();
        }
        }
  
全部資料51hei下載地址:
單片機設計——音樂計時器.zip (472.64 KB, 下載次數: 105)
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂2 踩
回復

使用道具 舉報

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

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

51hei.png
回復

使用道具 舉報

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

使用道具 舉報

地板
ID:462085 發表于 2020-3-6 16:56 | 只看該作者
不錯的設計,值得學習
回復

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

哇,我也是嗚嗚嗚,那你現在解決了嗎
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人深夜福利 | 九九综合 | 亚洲精品视频免费观看 | 天天精品在线 | 国产精品久久久久久久免费大片 | 黄色大片在线视频 | 中文字幕成人网 | 一区二区视频在线 | 国产精品久久久久久久白浊 | 亚洲欧美在线一区 | 免费一级欧美在线观看视频 | 天天av天天好逼 | 日韩不卡一二区 | 黑色丝袜三级在线播放 | 国产精品美女久久久久aⅴ国产馆 | 国产精品一区2区 | 毛片电影 | 中文字幕不卡一区 | 午夜久久久久久久久久一区二区 | 精品久久久久久久人人人人传媒 | 免费黄色大片 | 最新91在线| 欧美精品一区二区三区在线 | 国产视频第一页 | av官网在线 | 国产成人精品午夜 | 国产三级在线观看播放 | 性欧美xxxx | 精久久久| 亚洲激情第一页 | 中文字幕免费观看 | 亚洲高清在线观看 | 羞羞视频网| 欧美日本韩国一区二区 | 精品视频在线播放 | 亚洲国产精品成人综合久久久 | 欧美视频一区二区三区 | 天天艹天天干天天 | 视频在线一区二区 | 国产成人亚洲精品 | 国产成都精品91一区二区三 |