LED音乐频谱:
diy单片机音乐频谱全部制作资料下载:
LED音乐频谱文件.zip
(7.49 MB, 下载次数: 729)
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();
- }
复制代码
|