LED音樂頻譜:
diy單片機音樂頻譜全部制作資料下載:
LED音樂頻譜文件.zip
(7.49 MB, 下載次數: 730)
2016-4-17 17:48 上傳
點擊文件名下載附件
diy制作教程:
關于燈珠顏色的排列如下:下面我進行圖文詳細的介紹關于音樂頻譜的制作, 懶惰者可以直接看圖, 跳過文字的明, 因為圖片已經明一切了。 首先,我們要在 9*15cm 的洞洞板上焊接上 LED 燈,因此要先前量度好板子,合理分配每個 LED 燈的焊接位置,每一豎的光柱為 11 個,總共有 5 豎,經過分配后就可以焊接上LED,如圖所示,焊接LED 發光二極管,逐個放上 LED 燈在洞洞板上,然后在背面用焊錫固定好,引腳不要剪去,到后面還有用,焊接后就如圖所示。 根據你選用的洞洞板從而平均分配焊接位置,焊接好一豎的 LED 后就如圖所示, 這些都不難完成的, 要注意的是焊接 LED 的時候, 最好用一只手指按住 LED的草帽位置,然后用焊錫在背面焊接上固定,這樣就可以避免焊接出來的 LED 燈歪曲了。 按照同樣的方法焊接好其他幾排的 LED 燈。 直至焊接好所有的 LED 燈, 只要你覺得好看,之于怎么排列和如何選擇 LED 燈的顏色,我不管,反正你是對的。焊接好所有 LED 燈就如圖所示,這時候不要急著下一個步驟,先用 3V 的紐扣電池逐個測試每個 LED 是否能亮起,免得到最后發現有 LED 燈不亮就糟糕了,發現不亮就及時更換修改,因為引腳焊接時間過長會損害 LED 燈的,這里特別提醒一下 如圖所示為焊接好所有 LED 燈的背面, 注意 LED 燈的引腳不要弄歪了, 同時注意焊接點不要出現虛焊的情況,檢測完畢,下一步! 接下來,把 LED 燈的負極端(較短的一端引腳)逐個向下彎曲,如圖所示形成手拉手的狀 況, 這個是學習外國同志的做法。 由于小弟我思維不發達, 確實找不到比這種更好的處理方法,因此在這里借用一下,最終的研究成果歸所有,再次說明一下。 其他顏色的負極也向同一個方向擺在一邊, 要確保每一種顏色的 LED 負極端都接觸在一起,而且要注意彎曲的時候要盡量壓低負極的管腳高度。完成這一步驟后就如圖所示。 接下來是處理 LED 的正極端(較長的 LED 管腳) ,也按照同樣做法,把 LED 的正極端彎向右邊, 同時也要確保每一行的正極端接觸在一起, 特別要注意正極彎曲的時候不要接觸到之前的負極, 由于正極端管腳較長, 因此可以把正極彎曲后的高度高一些, 正極和負極要形成一定的高度差,如果還是不能確保彎曲后會互相接觸到的話, 最好就是用絕緣膠帶在每個交叉點粘上,以防誤觸。 如圖所示, 分別把正負極的接觸點都用焊錫焊接上, 固定好, 并且把多出的一部分管腳修剪掉,完成這一步,音樂頻譜的顯示部分就完成了。 接下來,是焊接音樂頻譜的控制部分電路,按照電路圖,控制部分的電路也較為簡單,先在 另一塊的 9*15的洞洞板下方焊接好單片機的 IC 插座和晶振部分電路, 焊接好就上圖所示,注意,IC 插座是倒著焊接的,還有,晶振選用的是 24MHZ,不要選錯了。 同時在背面焊接上 470 歐的貼片限流電阻(為了降低難度,發貨一律使用直插電阻),當然,如果沒有貼片電阻的也可以選擇直插電阻。 還有,分別在上下如圖所示位置上焊接上兩排 8 針的排針,同時還要在電源正負極之間焊 接上 0.1uf 的濾波電容,用以濾掉電源的高頻信號干擾,而且參照 STC 單片機的數據手冊, 還需在 AD 采集端口和地線之間要接上一個 47pf 電容。焊接完成后如圖所示。 接下來, 打開一個 3.5mm 的音頻插頭, 在內部用排線分別引出地線和左右聲道任意一個聲道線。選用合適長度的排線即可,最好選用內部是銅線的,減少干擾。 然后如圖所示,把兩條排線分別接上 AD 采集端口(我選用的是 P1.0 口)和地線,為了不使排線擺動時弄斷接觸部分,還要把兩根排線如圖用線捆綁固定住。 接下來,把兩條 8 針的杜邦線的一端剪去,在每一根排線的一端刨去熟料部分,使其露出銅芯,按照電路圖,用焊錫把每根線分別接上 LED 顯示部分的正極和負極,然后,對應好位置后把杜邦插座插座先前焊接好的排針上面,焊接完成后如圖所示。 在 IC 插座上插上下載好程序的單片機后,然后選用合適高度的銅柱子把兩塊洞洞板四個角 上的洞固定起來,這樣不僅可以保護內部的控制部分電路,而且顯示屏還可以立起來, 方便隨時更改擺放位置。完成后如圖上所示。 把一分二的音頻線分別插上音箱的音頻線和音樂頻譜的音頻線, 另一端插在電腦或者其他播放設備上面。 原理上講, 完成上面的部分作品都可以工作了, 但是長期使用,我發現音樂頻譜的顯示會出現不穩定的情況,也就是說在我還沒有插上播放設備上也會有所顯示,經過后來一番研究, 發現原來是電源輸出的不穩定因素造成的,之前的 0.1uf 電容已經把電源的高頻信號濾掉, 但是電源還有低頻的干擾信號,于是還要在電源正負極之間加上一個 100uf 左右的電容, 我加上 100uf 的電容后就不會出現之前的情況了。
- #include <stc12c5a60s2.h>//"stc12c5620ad.h"
- #include<intrins.h>
- #define LongToBin(n) (((n>>21)&0x80)|((n>>18)&0x40)|((n>>15)&0x20)|((n>>12)&0x10)|((n>>9)&0x08)|((n>>6)&0x04)|((n>>3)&0x02)|((n)&0x01))
- #define BIN(n) LongToBin(0x##n##)
- #define uchar unsigned char
- #define uint unsigned int
- #define SAMPLE_NUM 64
- #define NUM_2_LOG 6
- #define FFT_OUT_MIN 3
- uchar code BRTable[SAMPLE_NUM] ={ 0, 32, 16, 48, 8, 40, 24, 56,4, 36, 20, 52, 12, 44, 28, 60, 2, 34, 18, 50, 10, 42, 26, 58, 6, 38, 22, 54, 14, 46, 30, 62, 1, 33, 17, 49, 9, 41, 25, 57,5, 37, 21, 53, 13, 45, 29, 61,3, 35, 19, 51, 11, 43, 27, 59,7, 39, 23, 55, 15, 47, 31, 63};
- char code sin_tabb[SAMPLE_NUM] = { 0 ,12 ,25 ,37 ,49 ,60 ,71 ,81 ,90 ,98 ,106 ,112 ,117 ,122 ,125 ,126 ,127 ,126 ,125 ,122 ,117 ,112 ,106 ,98 ,90 ,81 ,71 ,60 ,49 ,37 ,25 ,12 ,0 ,-12 ,-25 ,-37 ,-49 ,-60 ,-71 ,-81 ,-90 ,-98 ,-106 ,-112 ,-117 ,-122 ,-125 ,-126 ,-127 ,-126 ,-125 ,-122 ,-117 ,-112 ,-106 ,-98 ,-90 ,-81 ,-71 ,-60 ,-49 ,-37 ,-25 ,-12 };
-
- char code cos_tabb[SAMPLE_NUM] = {127 ,126 ,125 ,122 ,117 ,112 ,106 ,98 ,90 ,81 ,71 ,60 ,49 ,37 ,25 ,12 ,0 ,-12 ,-25 ,-37 ,-49 ,-60 ,-71 ,-81 ,-90 ,-98 ,-106 ,-112 ,-117 ,-122 ,-125 ,-126 ,-127 ,-126 ,-125 ,-122 ,-117 ,-112 ,-106 ,-98 ,-90 ,-81 ,-71 ,-60 ,-49 ,-37 ,-25 ,-12 ,0 ,12 ,25 ,37 ,49 ,60 ,71 ,81 ,90 ,98 ,106 ,112 ,117 ,122 ,125 ,126 };
- uchar a[21];
- uchar keep,keepnum,anum,timernum,timernum2,lednum3,Ltime;//用于分離
- /*加入數組用于顯示相應led燈數目*/
- uchar lednum[]={0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};//0-7的顯示數組 P2組控制
- int xdata FftReal[SAMPLE_NUM];
- int xdata FftImage[SAMPLE_NUM];
- sbit p30=P3^0;
- sbit p31=P3^1;
- sbit p32=P3^2;
- sbit p33=P3^3;
- sbit p34=P3^4;
- sbit p35=P3^5;//9-11的led控制
- sbit p36=P3^6;
- sbit p37=P3^7;
- void timerinit()//定時器 初始化函數
- {
- TMOD=0x01;
- TH0=(65536-6000)/256;
- TL0=(65536-6000)%256;
- EA=1;
- ET0=1;
- TR0=1;
- }
- void disp()
- {
- timernum++;
- if(timernum==6) timernum=1;
- P2=0;//顯示前先關閉
- P3=P3&0x1f;
- switch(timernum)
- {
- case 1:anum=a[0];p34=0;p33=1;p32=1;p31=1;p30=1;break;
- case 2:anum=a[1];p34=1;p33=0;p32=1;p31=1;p30=1;break;
- case 3:anum=a[2];p34=1;p33=1;p32=0;p31=1;p30=1;break;
- case 4:anum=a[3];p34=1;p33=1;p32=1;p31=0;p30=1;break;
- case 5:anum=a[4];p34=1;p33=1;p32=1;p31=1;p30=0;break;
- }
- //anum=a[10];/*修改可以改變光柱高度 (anum值分開幾個部分用定時器區分顯示)(a[]內逐加) */
- if(anum<=8){P2=lednum[anum];P3=P3&0x1f;}//屏蔽高三位
- //else {P2=0xff;P3=lednum2[anum-9];}
- if(anum==9){P2=0xff;p35=1;p36=0;p37=0;}
- if(anum==10){P2=0xff;p35=1;p36=1;p37=0;}
- if(anum==11){P2=0xff;p35=1;p36=1;p37=1;}
- }
- uchar STC_ADC() //!!根據數據手冊寫一個ad讀取函數
- {
- uchar i;
- ADC_RES = 0;
- ADC_RESL = 0;
- ADC_CONTR = BIN(10001000);
- i=3;
- while(i--);
- while (1)
- {
- if (ADC_CONTR & BIN(10000))
- {
- break;
- }
- }
- ADC_CONTR = BIN(10000000);
- return( ADC_RESL<<2) ;
- }
- short sqrt_16( unsigned long M)
- {
- unsigned int N, i;
- unsigned long tmp, ttp;
- if( M == 0 )
- return 0;
-
- N = 0;
-
- tmp = ( M >> 30 );
- M <<= 2;
- if( tmp > 1 )
- {
- N ++;
- tmp -= N;
- }
-
- for( i=15; i>0; i-- )
- {
- N <<= 1;
-
- tmp <<= 2;
- tmp += (M >> 30);
-
- ttp = N;
- ttp = (ttp<<1)+1;
-
- M <<= 2;
- if( tmp >= ttp )
- {
- tmp -= ttp;
- N ++;
- }
- }
-
- return N;
- }
- void FFT()
- {
- register uchar i,bb,j,k,p,max;
- register short TR,TI,temp;
- unsigned long ulReal;
- unsigned long ulImage;
-
-
-
- for(i=0; i<SAMPLE_NUM;i++) //此處可以加入自動增益
- {
- FftReal[BRTable[i]] = STC_ADC()<<keep;//使顯示保持在一定范圍內
- FftImage[i] = 0;
- }
- keepnum=FftReal[2]/32;//提取等級數
- if((7<keepnum)&&(keepnum<=8)) {keep=1;}
- else if((4<keepnum)&&(keepnum<=6)) {keep=2;}
- else if((2<keepnum)&&(keepnum<=4)) {keep=3;}
- else {keep=5;}
-
- for( i=1; i<=NUM_2_LOG; i++)
- {
- bb=1;
- bb <<= (i-1);
- for( j=0; j<=bb-1; j++)
- {
- p=1;
- p <<= (NUM_2_LOG-i);
- p = p*j;
- for( k=j; k<SAMPLE_NUM; k=k+2*bb)
- {
- TR = FftReal[k]; TI = FftImage[k]; temp = FftReal[k+bb];
- FftReal[k] = FftReal[k] + ((FftReal[k+bb]*cos_tabb[p])>>7) + ((FftImage[k+bb]*sin_tabb[p])>>7);
- FftImage[k] = FftImage[k] - ((FftReal[k+bb]*sin_tabb[p])>>7) + ((FftImage[k+bb]*cos_tabb[p])>>7);
- FftReal[k+bb] = TR - ((FftReal[k+bb]*cos_tabb[p])>>7) - ((FftImage[k+bb]*sin_tabb[p])>>7);
- FftImage[k+bb] = TI + ((temp*sin_tabb[p])>>7) - ((FftImage[k+bb]*cos_tabb[p])>>7);
-
- FftReal[k] >>= 1;
- FftImage[k] >>= 1;
- FftReal[k+bb] >>= 1;
- FftImage[k+bb] >>= 1;
-
- }
- }
- }
- max=0;
- for( i=0; i<5; i++)//5
- {
- ulReal = FftReal[i+1];
- ulReal *= ulReal;
- ulImage = FftImage[i+1];
- ulImage *= ulImage;
-
- a[i] = sqrt_16( ulReal + ulImage ); //修改
-
- if( a[i] < FFT_OUT_MIN )
- a[i] = 0;//修改
- else
- a[i] = a[i]-FFT_OUT_MIN;
- if( a[i] >max)
- max =a[i];
- //disp();
- }
- if(max>11) //11
- {
- max/=11;
- for( i=0; i<5; i++) //輸出a的5個分離數值
- {
- a[i]/=max;
-
- }
- }
- }
- void main()
- {
- P2M0=0xff;// BIN(11111111);//P2組設置為推挽輸出
- P2M1=0;
- P3M0=0xe0;// BIN(11111111);
- P3M1=0;
- P1M0=0x00;
- P1M1=0x01;
- P1ASF =1; //設置P1.0為AD口
- AUXR1 =BIN(100);
- keep=0;
- keepnum=0;
- timerinit();//定時器初始化
- timernum=3;//從3開始
- timernum2=0;
- while(1)
- {
- FFT();
- }
- }
- void timer0() interrupt 1
- {
- TH0=(65536-6000)/256; //6000
- TL0=(65536-6000)%256;
- disp();
- }
復制代碼
|