STC硬件主板--電子樂譜展示的設計

摘要:本設計基於我們所學習的單片機課程講座、實例以及自學,掌握單片機技術是一門不可或缺的技術,對我們將來的工作以及生活都有密切的聯繫。單片機是一種集成電路芯片,是採用超大規模集成電路技術把具有數據處理能力的中央處理器CPU隨機存儲器RAM、只讀存儲器ROM、多種I/O口和中斷系統、定時器/計時器等功能(可能還包括顯示驅動電路、脈寬調製電路、模擬多路轉換器、A/D轉換器等電路)集成到一塊硅片上構成的一個小而完善的微型計算機系統,在工業控制領域的廣泛應用。從上世紀80年代,由當時的4位、8位單片機,發展到現在的32300M的高速單片機。

 

關鍵詞:IAP15F2K61S2芯片  STC89C51單片機  蜂鳴器 數碼管 led燈 中斷 定時器 嵌入式系統

 

前言:近年來,隨着電子技術和微機計算機的迅速發展,單片機的檔次不斷提高,其運用領域也在不斷的擴大,已在工業控制,尖端科學,智能儀器儀表,日用家電,汽車電子系統,辦公自動化,個人信息終端及通信產品中得到了廣泛的運用,成爲現代電子系統中最重要的智能化的核心部件,在嵌入式系統中充當着人體頭腦的最重要的作用。

 

一、課程設計目的,任務要求

設計概述:該設計的目的是設計出一個可以顯示電子音樂的樂譜的工程。我們經常可以在酷狗,蝦米音樂等等音樂app裏使用聽歌識曲的功能,哼着一個沒有歌詞的調子就可以搜出這個歌曲,對於喜歡音樂的人來說極其便捷。顯然,通過一個曲調就識別然後匹配出相應的歌曲,這裏必可以通過識別這首歌的一段樂譜,然後在樂曲庫裏尋找和這段曲調相似的歌曲。另一方面,有些人的確在音樂方面比較懵懂,播放一個樂曲直接學,很多調都聽不準所以學不準,如果只有音樂沒有樂譜,對於學習音樂就比較困難。所有如果能識別出音樂的樂譜並輸出給人們看,會大大減小學習音樂的困難,是音樂感不強的人學音樂的福利。

 任務要求:播放一段音樂,通過不同按鍵控制不同顯示樂譜的方式,在數碼管上顯示簡譜,或者用led燈顯示樂譜。

 二、程序的設計流程圖

 

播放音樂子程序設計流程圖如下:

整個程序設計流程圖如下:

 


三、程序相關電路及工作原理說明

1.IAP15F2K61S2芯片40個引腳如下:

sbit beep=P3^4;                //蜂鳴器引腳

sbit sel_led=P2^3;           //控制數碼管和led燈轉換的引腳

sbit sel_0=P2^0;

sbit sel_1=P2^1;

sbit sel_2=P2^2;              //控制三個進位的引腳

sbit key1=P3^2;

sbit key2=P3^3;

sbit key3=P1^7;                    //3個按鍵引腳

2.共陰極數碼管電路圖如下: P0口輸入高電壓led燈亮

3.按鍵電路示意圖:按下是低電平, 高電平時常態

4.無源蜂鳴器電路示意圖如下:輸入方波,發出聲音

四、程序設計框架

1.宏定義

#defineuint unsigned int

#defineuchar unsigned char

2.變量定義

bit k1=0;

bit k2=0;

bit k3=0;                               //控制三種樂譜顯示方式的標誌位

uchar qudiao,jp,weizhi;          //曲調 音符 位置

uchar duanxuan[]                  //定義段選 數碼管從0-7

uchar led[]                   //定義0-8led燈亮的情況

uchar timeh,timel;            //定義定時器的重裝值 表示不同的頻率


3.程序函數說明

      voiddelay(unsigned int xms)  //延時程序

      ucharquyin(uchar tem)              //找到tem音符在quzi數組中的位置值,識別輸入的音符,並根據不同的按鍵按下來控制不同的樂譜輸出方式

      voidplaymusic()                      //播放音樂函數

      voidinit()                           //定時器初始化配置io口(系統初始化)

void tim1()interrupt 1          //定時器0中斷服務程序,重新裝值,產生方波,對應蜂鳴器發聲

 

五、下載與調試(實驗日誌)

1.   2016.8.22  問題:程序下載到板子上沒有反映,沒有顯示

解決思路:顯示電路主要有usb口 、晶振片和iap15f2k61s2芯片組成,檢測到usb口電路沒有焊錯,應該就是晶振片壞了。

解決過程:換了晶振,果然可以了。

已解決。

 

2.  2016.8.30 霍爾實例下載驗證不了

解決思路:磁鐵靠近與遠離,霍爾元器件沒有任何反應,檢查霍爾元器件,發現正負極焊反了。

解決過程:把霍爾元器件再重新焊對一遍。

已解決。

 

3.  2016.9.2 設計樂譜顯示工程:

2016.9.2:剛開始只設計出一種在數碼管上顯示樂譜的顯示方式,也沒有按鍵控制功能。

多次修改程序,下載驗證成功。

2016.9.3:加一個用led燈來輸出樂譜的方式,沒有按鍵功能。

多次修改程序,下載驗證成功。

2016.9.4:在原來的基礎上,用按鍵來控制選擇哪種方式來輸出樂譜。

多次修改程序,下載驗證成功。

 

六、總結與心得體會

學習c51單片機,我覺得最重要也最基礎應該要搞懂中斷和定時器這兩個問題。中斷就是cpu在處理A事件,B事件發生(中斷產生)了並要求cpu馬上處理(發出中斷請求),cpu轉去處理B事件(中斷響應),並執行中斷處理程序(中斷服務),處理完後返回處理A事件(中斷返回)。畫個流程圖,就是:中斷產生-->中斷響應-->中斷服務-->中斷返回c51單片機裏有五種中斷源,分別是外部中斷0,定時器中斷0,外部中斷1,定時器中斷1與串行口。搞明白了中斷源,還要明白中斷響應是有條件的,要符合三個條件:一個是cpu要開中斷開關(EA=1),一個是中斷源有請求,一個是中斷允許位爲1。定時器就要明白一個機械週期等於12個振盪週期,如果是12MHZ的晶振片,那麼一個計數週期T=1/(12*10^6) *12=10^(-6)=1us16位計數器總的就是65536us,最多了可以定時65ms。軟件程序的調試一般可以把重點放在分模塊調試上,統調是最後一環,通過各模塊的單步或跟蹤調試,使程序逐步趨於正確,最後統調程序。

 

七、參考文獻

1.51單片機c語言應用程序設計實例精講》        戴佳 戴衛恆編著             電子工業出版社

2.《計算機硬件技術基礎實驗教程》     方愷晴主編  清華大學出版社

3.《單片機原理與運用及c51程序設計》 楊家國 清華大學出版社

4.51單片機課程設計》               周向紅 華中科技大學出版社

5.10天學會51單片機視頻             郭天祥主講   

6.C15單片機及c語言知識點必備祕籍

7.51單片機學習論壇

8.百度百科      

 

附錄:源程序

/**********************

說明:直接播放音樂key1鍵就顯示在led燈上顯示樂譜

                                                                      key2鍵就在數碼管7上顯示樂譜

                                                                      key3鍵就在數碼管0上顯示音調

 

***********************/

 

#include <STC15F2K60S2.h>

#define uint unsigned int

#define uchar unsigned char

sbit beep=P3^4;                     //蜂鳴器引腳

sbit sel_led=P2^3;         //數碼管和led轉換引腳

sbit sel_0=P2^0;

sbit sel_1=P2^1;

sbit sel_2=P2^2;                   //控制3個進位的管腳

sbit key1=P3^2;

sbit key2=P3^3;

sbit key3=P1^7;                          //控制三個按鍵k1 k2 k3 的引腳

 

bit k1=0;

bit k2=0;

bit k3=0;                                    //控制3個樂譜顯示方式的標誌位

 

uchar qudiao,jp,weizhi;          //定義曲調,音符和位置

ucharduanxuan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07}; //數碼管顯示0-7

ucharled[]={0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //led燈從左到右分別亮

uchar timeh,timel;           //定義定時器的重裝值

uchar code music[] ={ 

0x33,0x10,0x32,0x10,0x33,0x10,0x32,0x10,0x33,0x10,  //音樂代碼:《致愛麗絲》

0x27,0x10,0x32,0x10,0x31,0x10,0x26,0x20,

0x23,0x10,0x26,0x10,0x31,0x10,0x27,0x20,

0x23,0x10,0x31,0x10,0x27,0x10,0x26,0x20,

0x31,0x10,0x31,0x10,0x32,0x10,0x33,0x20,

0x25,0x10,0x34,0x10,0x33,0x10,0x32,0x20,

0x25,0x10,0x33,0x10,0x32,0x10,0x31,0x20,

0x25,0x10,0x32,0x10,0x31,0x10,0x27,0x20,

0x23,0x10,0x31,0x10,0x27,0x10,0x26,0x20,

  //音樂代碼,歌曲爲《同一首歌》,格式爲: 音符, 節拍, 音符, 節拍,   

0x15,0x20,0x21,0x10,   //音符的十位代表是低八度,中八度還是高八度,1代表高八度,2代表中八度,3代表高八度

0x22,0x10,0x23,0x15,   //個位代表簡譜的音符,例如0x15代表低八度的S00x21代表中八度的DO

0x24,0x05,0x23,0x10,   //節拍則是代表音長,例如:0x10代表一拍,0x20代表兩拍,0x05代表1/2

0x21,0x10,0x22,0x20,

0x21,0x10,0x16,0x10,

0x21,0x40,0x15,0x20,

0x21,0x10,0x22,0x10,

0x23,0x10,0x23,0x05,

0x24,0x05,0x25,0x10,

0x21,0x10,0x24,0x15,

0x23,0x05,0x25,0x10,

0x22,0x05,0x23,0x05,

0x23,0x05,0x22,0x05,

0x22,0x30,0x23,0x20,

0x25,0x10,0x31,0x10,

0x27,0x15,0x26,0x05,

0x26,0x20,0x25,0x10,

0x25,0x05,0x26,0x05,

0x27,0x10,0x26,0x05,

0x25,0x05,0x23,0x40,

0x24,0x15,0x24,0x05,

0x25,0x10,0x26,0x10,

0x25,0x10,0x24,0x05,

0x23,0x05,0x22,0x20,

0x17,0x10,0x17,0x05,

0x16,0x05,0x15,0x10,

0x16,0x10,0x21,0x40,

0x00,0x00

};

uchar code quzi[] ={        //此數組數據爲各個音符在定時器中的重裝值,第一列是高位,第二列是低位

0xf8,0x8c,        //低八度,低1

0xf9,0x5b,       

0xfa,0x15,        //3

0xfa,0x67,

0xfb,0x04,        //5

0xfb,0x90,

0xfc,0x0c,        //7  

0xfc,0x44,        //中央C調

0xfc,0xac,        //2

0xfd,0x09,

0xfd,0x34,        //4

0xfd,0x82,

0xfd,0xc8,        //6

0xfe,0x06,

0xfe,0x22,        //高八度,高1  

0xfe,0x56,

0xfe,0x6e,        //3

0xfe,0x9a,

0xfe,0xc1,        //5

0xfe,0xe4,

0xff,0x03  //7

};

/**********************

函數名稱:voiddelay(unsigned int xms)

功能描述:延時

入口參數:xms:輸入需要延時的毫秒值

出口參數:無

備註:

 

***********************/

void delay(unsigned int xms)

{

       uinti,j;                                         

        for(i=xms;i>0;i--)

             for(j=124;j>0;j--);

}

 

/**********************

函數名稱:voidinit()

功能描述:系統初始化,功能是配置IO  定時器的初始化

入口參數:無

出口參數:無

備註:

 

//P2^0,P2^1,P2^2,P2^3都設爲推輓輸出

***********************/

void init()

{

       P0M0=0x00;

       P0M1=0x00;

       P2M0=0x0f; 

       P2M1=0x00;

       P3M0=0x10;

       P3M1=0x00;

       P4M0=0x00;

       P4M1=0x00;

       P5M0=0x00;

       P5M1=0x00;

      

       TMOD=0x01;

       TH0=0xD8;

       TL0=0xEF;

       EA=1;

       ET0=1;

       TR0=0;

}

 

/**********************

函數名稱:ucharquyin(uchar tem)

 

功能描述:識別輸入的音符並且控制3個不同key鍵的按下來控制不同的樂譜輸出方式

quzi數組中,找到music數組定義的簡譜音符的重裝值,並返回其在quzi數組中的位置

入口參數:temmusic數組中定義的簡譜音符

出口參數:返回的是tem音符在quzi數組中的位置值

備註:

 

***********************/

uchar quyin(uchar tem)

{

              qudiao=tem/16;                             //4位是曲調值

       jp=tem%16;                           //4位是音符

      

       if(key1==0)

       {k3=0;

              k2=0;

              k1=1;

}

       if(k1==1)

       {

                     sel_led=1;   //選擇led燈亮來顯示樂譜

                P0=led[jp];

}

                    

       if(key2==0)

       {

              k2=1;

              k1=0;

              k3=0;

}

if(k2==1)

{

              sel_led=0;//先選數碼管亮

              sel_0=1;

              sel_1=1;

              sel_2=1;

              P0=duanxuan[jp];  //選數碼管輸出音符樂譜

              delay(1);

}

      

       if(key3==0)

       {

              k1=0;

              k2=0;

              k3=1;

      

}

 

if(k3==1)

{

       sel_led=0;

              sel_0=0;

              sel_1=0;

              sel_2=0;

              P0=duanxuan[qudiao];//用數碼管輸出曲調

              delay(1);

}

 

      

      

      

       if(qudiao==1)                        //當曲調值爲1時,即是低八度,低八度在quzi數組中基址爲0

              qudiao=0;

       elseif(qudiao==2)                  //當曲調值爲2時,即是中八度,中八度在quzi數組中基址爲14

              qudiao=14;

       elseif(qudiao==3)                  //當曲調值爲3時,即是高八度,高八度在quzi數組中,基址爲28

              qudiao=28;

       weizhi=qudiao+(jp-1)*2;               //通過基址加上音符作爲偏移量,即可定位此音符在quzi數組中的位置

       returnweizhi;                         //返回這一個位置值

}

/**********************

函數名稱:voidplaymusic()

功能描述:播放音樂

入口參數:無

出口參數:無

備註:

 

***********************/

void playmusic()

{

       ucharp,m,tem;   //m爲節拍  

       uchari=0;   

       while(1)  

       {  

              p=music[i];           //如果碰到結束符,延時1,回到開始再來一遍

              if(p==0x00)

              {

                     i=0;

                     delay(1000);

              }       

              elseif(p==0xff)   //若碰到休止符,延時100ms,繼續取下一音符

              {

                     i=i+2;

                     delay(100);

                     TR0=0;

              }     

              else                   //正常情況下取音符和節拍

              {

                     tem=quyin(music[i]);            //取出當前音符在quzi數組中的位置值

                     timeh=quzi[tem];                 //把音符相應的計時器重裝載值賦予timehtimel

                     timel=quzi[tem+1];

                     i++;

                     TH0=timeh;                                //timehtimel賦予計時器

                     TL0=timel;

                     m=music[i];                                //取得節拍

                     i++;

              }

              TR0=1;                                             //開定時器1   

              delay(m*180);             //等待節拍完成, 通過P3^4口輸出音頻   

              TR0=0;                                            //關定時器1

                       

   }

}

 

 

 

//主函數入口

void main()

{

       init();

       P0=0x00;

       playmusic();

       while(1);

}

 

 

 

/**********************

函數名稱:voidtim1() interrupt 1

功能描述:定時器0中斷處理,重新裝值,並把beep值取反,產生方波

入口參數:無

出口參數:無

備註:

 

***********************/

void tim1() interrupt 1                                       //計時器控制頻率

{

       TH0=timeh;

       TL0=timel;

       beep=~beep;

}

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章