|
16x16音乐频谱(源代码 原理图)
部分源码预览:
- #include "STC12C5A.h"
- #include <intrins.h>
- #include <math.h>
- #include "DS1302.h"
- #include "Led.h"
- #define uchar unsigned char
- #define uint unsigned int
- #define BinToHex(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 B(n) BinToHex(0x##n##l) // 8位2进制宏
- uchar code ColScan_2[16] = {0x17,0x13,0x15,0x11,0x16,0x12,0x14,0x10,
- 0x27,0x23,0x25,0x21,0x26,0x22,0x24,0x20}; // 74hc138 进行列扫描
- float code iw[64]=
- {
- 1.000,0,0.9952,-0.0980,0.9808,-0.1951,0.9569,-0.2903,0.9239,-0.3827,0.8819,-0.4714,0.8315,-0.5556,
- 0.7730,-0.6344,0.7071,-0.7071,0.6344,-0.7730,0.5556,-0.8315,0.4714,-0.8819,0.3827,-0.9239,0.2903,-0.9569,
- 0.1951,-0.9808,0.0980,-0.9952,0.0,-1.0000,-0.0980,-0.9952,-0.1951,-0.9808,-0.2903,0.9569,-0.3827,-0.9239,
- -0.4714,-0.8819,-0.5556,-0.8315,-0.6344,-0.7730,-0.7071,-0.7071,-0.7730,-0.6344,-0.8315,-0.5556,-0.8819,-0.4714,
- -0.9239,-0.3827,-0.9569,-0.2903,-0.9808,-0.1951,-0.9952,-0.0980
- };
- uint data LEDBuf[16];
- uint idata refreshflag[16];
- uchar fft_sign = 0; // 进行fft变换标志位
- struct compx
- {
- float real;
- float imag;
- };
- struct compx dd[65]; // FFT数据
- data struct compx temp;
- void delay500ms(void)
- {
- unsigned char a,b,c,n;
- for(c=218;c>0;c--)
- for(b=79;b>0;b--)
- for(a=238;a>0;a--);
- for(n=4;n>0;n--);
- }
- void Delay(uint n)
- {
- uint x;
- while (n--)
- {
- x = 5000;
- while (x--);
- }
- }
- void GPIO_Init() // GPIO口的初始化
- {
- P1M1 = B(00000011);
- P1M0 = B(00000000);
- P1 = B(00000011);
- P1ASF = B(00000011);
- }
- void Interrupt_Init(void) // 单片机中断初始化
- {
- TMOD = 0x01; // 高4位控制T/C1
- EA = 1; // 开总中断
- TH0 = 0x00; // 16位计数寄存器T1高8位
- TL0 = 0x00; // 16位计数寄存器T1低8位
- ET0 = 1; // T/C1中断开
- TR0 = 1; // T/C1启动
- }
- void ADC_Init() // 集成ADC的初始化(官方函数)
- {
- ADC_RES = 0; //Clear previous result
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
- Delay(2); //ADC power-on and delay
- }
- uchar GetADCResult(uchar ch) // 进行AD转换(官方函数)
- {
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
- _nop_(); //Must wait before inquiry
- _nop_();
- _nop_();
- _nop_();
- while (!(ADC_CONTR & ADC_FLAG));//Wait complete flag
- ADC_CONTR &= ~ADC_FLAG; //Close ADC
- return ADC_RES; //Return ADC result
- }
- void ee(struct compx b1,uchar b2) //复数乘法
- {
- temp.real=b1.real*iw[2*b2]-b1.imag*iw[2*b2+1];
- temp.imag=b1.real*iw[2*b2+1]+b1.imag*iw[2*b2];
- }
- uint mypow(uchar nbottom,uchar ntop) //乘方函数
- {
- uint result=1;
- uchar t;
- for(t=0;t<ntop;t++)result*=nbottom;
- return result;
- }
-
- void fft(struct compx *xin,uchar data N) //快速傅立叶变换
- {
- uchar data fftnum,i,j,k,l,m,n,disbuff,dispos,dissec;
- data struct compx t;
- fftnum=N; //傅立叶变换点数
- for(m=1;(fftnum=fftnum/2)!=1;m++);//求得M的值
- for(k=0;k<=N-1;k++) //码位倒置
- {
- n=k;
- j=0;
- for(i=m;i>0;i--) //倒置
- {
- j=j+((n%2)<<(i-1));
- n=n/2;
- }
- if(k<j){t=xin[1+j];xin[1+j]=xin[1+k];xin[1+k]=t;}//交换数据
- }
- for(l=1;l<=m;l++) //FFT运算
- {
- disbuff=mypow(2,l); //求得碟间距离
- dispos=disbuff/2; //求得碟形两点之间的距离
- for(j=1;j<=dispos;j++)
- for(i=j;i<N;i=i+disbuff) //遍历M级所有的碟形
- {
- dissec=i+dispos; //求得第二点的位置
- ee(xin[dissec],(uint)(j-1)*(uint)N/disbuff);//复数乘法
- t=temp;
- xin[dissec].real=xin[i].real-t.real;
- xin[dissec].imag=xin[i].imag-t.imag;
- xin[i].real=xin[i].real+t.real;
- xin[i].imag=xin[i].imag+t.imag;
- }
- }
- }
- void processfft(uchar num)
- {
- uchar pt;
- uint tmp;
- for(pt=1;pt<65;pt++)
- {
- dd[pt].imag=0; //清零虚部
- }
- fft(dd,64); //对当前数据进行傅立叶变换
- for(pt=1;pt<33;pt++)
- {
- dd[pt].real=sqrt(dd[pt].real*dd[pt].real+dd[pt].imag*dd[pt].imag);//取均方根
- }
- switch(num)
- { // 选择显示模式
- case 1: {
- for(pt=0;pt<16;pt++) // style 1
- {
- LEDBuf[pt]=0xffff;
- tmp = dd[(pt+1)*2].real;
- tmp = (tmp/16)+1;
- LEDBuf[pt]<<=tmp;
- LEDBuf[pt]=~(LEDBuf[pt]);
- }
- break;
- }
- case 2: {
- for(pt=0;pt<16;pt++) // style 2
- {
- if(refreshflag[pt]<(dd[pt].real/16)+1)
- {
- LEDBuf[pt]=0xffff;
- tmp = dd[(pt+1)*2].real;
- tmp = (tmp/16)+1;
- refreshflag[pt] = tmp;
- LEDBuf[pt]<<=tmp;
- }
- else
- {
- if(refreshflag[pt]>1)
- {
- refreshflag[pt]--;
- }
- LEDBuf[pt]=0xffff;
- tmp = refreshflag[pt];
- LEDBuf[pt]<<=tmp;
- }
- LEDBuf[pt]=~(LEDBuf[pt]);
- }
- break;
- }
- case 3: { // style 3
- for(pt=0;pt<16;pt++)
- {
- LEDBuf[pt]=0xffff;
- tmp = dd[(pt+1)*2].real;
- tmp = (tmp/16)+1;
- if(refreshflag[pt]<tmp)
- {
- refreshflag[pt] = tmp;
- }
- else
- {
- if(refreshflag[pt]>1)
- {
- refreshflag[pt]--;
- }
- tmp = refreshflag[pt];
- }
- LEDBuf[pt]&=(0x0001<<(tmp-1));
- }
- break;
- }
- case 4: { // style 4
- for(pt=0;pt<16;pt++)
- {
- LEDBuf[pt]=0xffff;
- tmp = dd[(pt+1)*2].real;
- tmp = (tmp/16)+1;
- LEDBuf[pt]<<=tmp;
- LEDBuf[pt]=~(LEDBuf[pt]);
- if(refreshflag[pt]<tmp)
- {
- refreshflag[pt] = tmp;
- }
- else
- {
- if(refreshflag[pt]>1)
- {
- refreshflag[pt]--;
- }
- tmp = refreshflag[pt];
- }
- LEDBuf[pt]|=(0x0001<<(tmp-1));
- }
- }
- }
- }
- void main()
- {
- uchar i,num=1;
- uint n;
- GPIO_Init(); // io口初始化
- ADC_Init(); // 集成adc初始化
- DS1302Init(); // 初始化1302
- MyLove(); // 开机动画
- while(GetADCResult(0)+GetADCResult(1)==0) // 没有插入耳机时
- {
- DisplayTime(); // 显示时间
- TimeSetting(); // 时间设定
- }
- for(i=0;i<16;i++) // 清空数据缓存
- {
- refreshflag[i] = 0x0000;
- }
- Interrupt_Init();
- while(1)
- {
- if(fft_sign == 1) // 读取频率为20Hz
- {
- fft_sign = 0;
- for(i=0;i<65;i++)
- {
- dd[i].real=(GetADCResult(0)+GetADCResult(1))<<2; // 读取ad结果并放大4倍;
- }
- processfft(num); // 傅立叶变化及处理
- }
- for(i=0;i<16;i++)
- { // 显示
- LineInput(0x0000);
- P2 = ColScan_2[i];
- LineInput(LEDBuf[i]);
- n = 512;
- while(n--);
- LineInput(0x0000);
- }
- if(ACT_Key == 0) // 动作检测,切换效果
- {
- num++;
- if(num>4)
- {
- num = 1;
- }
- delay500ms();
- }
- }
- }
- void Timer0() interrupt 1 //20hz
- {
- TL0 = 0x3c;
- TH0 = 0xb0;
- fft_sign = 1;
- }
-
复制代码
|
|