初学者都被这个程序弄得没信心了!
时间:10-02
整理:3721RD
点击:
#include<stc12c5a60s2.h>
#include<math.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define ADC_POWER 0x80 //ADC power control bit
#define ADC_FLAG 0x10 //ADC complete flag
#define ADC_START 0x08 //ADC start control bit
#define ADC_SPEEDLL 0x00 //420 clocks
#define ADC_SPEEDL 0x20 //280 clocks
#define ADC_SPEEDH 0x40 //140 clocks
#define ADC_SPEEDHH 0x60 //70 clocks
uchar LEDBuf[35];
uchar gain=6;
uchar Menu=2;
uchar refreshflag[40];
//#include<fft.h>
struct compx
{
float real;
float imag;
};
struct compx dd[65]; //FFT数据
data struct compx temp;
code float 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
};
//复数乘法
void ee(struct compx b1,uchar data 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 data nbottom,uchar data ntop)
{
uint data result=1;
uchar data 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;
}
}
}
//完成显示数据的转换工作,包括顶点下落速度控制以及顶点更新定格
//对fft数据进行处理,得到各个频率段的电压幅值
void processfft(void)
{
uchar data pt=0,tmp;
for(pt=1;pt<65;pt++)
{
dd[pt].imag=0; //清零虚部
}
fft(dd,64); //对当前数据进行傅立叶变换
for(pt=1;pt<65;pt++)
{
dd[pt].real=sqrt(dd[pt].real*dd[pt].real+dd[pt].imag*dd[pt].imag);//取均方根
}
if(Menu==1)
{
for(pt=2;pt<34;pt+=2)
{
for(tmp=(dd[pt].real/32)+1,LEDBuf[pt]=0xFF;tmp>=1;tmp--)//tmp>1;不保留最低位那一行常亮
{
LEDBuf[pt]<<=1;
}
LEDBuf[pt]=~(LEDBuf[pt]);
}
}
else if(Menu==2)
{
//下落感
for(pt=2;pt<34;pt+=2)
{
tmp=(dd[pt].real/32)+1;
if(refreshflag[pt]<tmp) //刷新数据,取较大高度值 存储显示
{
for(LEDBuf[pt]=0xFF;tmp>1;tmp--) //tmp>1;不保留 最低位那一行常亮;{}一次也不执行;
{
LEDBuf[pt]<<=1;
}
refreshflag[pt]=(dd[pt].real/32)+1;
}
else
{
if(refreshflag[pt]>1)refreshflag[pt]--; //顶端下落速度控制 改变值可以改变下降速度
for(LEDBuf[pt]=0xFF,tmp=refreshflag[pt];tmp>1;tmp--) //tmp>1;不保留 最低位那一行常亮
{
LEDBuf[pt]<<=1;
}
}
}
}
else if(Menu==0)
{
//下落感频谱
for(pt=2;pt<34;pt+=2)
{
tmp=(dd[pt].real/32)+1;
if(refreshflag[pt]<tmp) //刷新数据,取较大高度值 存储显示
{
for(LEDBuf[pt]=0xFF;tmp>=1;tmp--)//tmp>1;不保留 最低位那一行常亮;{}一次也不执行;
{
LEDBuf[pt]<<=1;
}
refreshflag[pt]=(dd[pt].real/32)+1;
}
else
{
if(refreshflag[pt]>1)refreshflag[pt]--;
for(LEDBuf[pt]=0xFF,tmp=refreshflag[pt];tmp>=1;tmp--)
{
LEDBuf[pt]<<=1;
}
}
LEDBuf[pt]=~(LEDBuf[pt]);
}
}
}
void delay(uchar t)
{
uchar a=2,j;
while(--a)
{
for(j=t;j>0;j--);
} for(j=t;j>0;j--);
}
void InitADC() //AD初始化
{
ADC_RES = 0; //Clear previous result
ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
delay(10);//ADC power-on and delay
}
uchar GetADCResult(uchar ch)//是几通道就输入几 {
{
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 IOINT()
{
P1ASF=0X03;
P0=0Xff;
P2=0X00;
P3=0X00;
}
void LEDBufrefresh(void)//频谱显示程序
{
uchar data i,x,y;
for(x=1,i=2;x!=0;x<<=1,i+=2)//移位;
{
P2=x;
for(y=1;y!=0;y<<=1)
{
P0=y&LEDBuf[i];
delay(2);
P0=0xff;
}
P2=0x00;
}
for(x=1,i=2;x!=0x80;x<<=1,i+=2)
{
P3=x;
for(y=1;y!=0;y<<=1)
{
P0=y&LEDBuf[i];
delay(2);
P0=0xff;
}
P3=0;
}
}
void time(void)//定时器开启
{
EA=0;
TMOD=0x01;
TH0=0x00;
TL0=0x00;
TR0=1;
ET0=1;
EA=1;
}
void main()
{
uint data Count=700;
uchar data i,Cgain,num=0;
IOINT();
for(i=0;i<=34;i++)
{
LEDBuf[i]=0x00;
}
for(i=0;i<=39;i++)
{
refreshflag[i]=0x09;
}
InitADC();
time();
while(1)
{ for(i=0;i<65;i++)
{
dd[i].real=(GetADCResult(0)+GetADCResult(1))<<gain; //读取ad结果并放大;
}
processfft();//傅立叶变化及处理
if(dd[2].real<32)
{
if(++Count==300) //电平值过小,这降低gain,减少噪音的电平显示;
{
Count=0;
//if(++Menu==4)Menu=0; //切换Menu,显示方式;
gain=6;
}
}
else
{
Count=1;
if(++num==0xAF) //播放时,Auto gain;
{
num=0; //自动增益;Automatic gain;
Cgain=dd[2].real/32;
if(7<Cgain<=8)
{
gain=4;
}
else if(4<Cgain<=6)
{
gain=5;
}
else if(2<Cgain<=4)
{
gain=6;
}
else
{
gain=7;
}
}
}
}
}
void LED() interrupt 1 using 1
{
TR0=0;
LEDBufrefresh();
TL0=0x00;
TH0=0x50;
TR0=1;
根据别人的频谱程序改来的这个程序,他是说要35M的晶振而我手上只有12M的就用了12M的,把延时时间改了一下,但每次运行程序都是满屏的闪烁,看不到频谱,哪位大神帮我看一下,新人,这个问题困惑我好久了!
#include<math.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define ADC_POWER 0x80 //ADC power control bit
#define ADC_FLAG 0x10 //ADC complete flag
#define ADC_START 0x08 //ADC start control bit
#define ADC_SPEEDLL 0x00 //420 clocks
#define ADC_SPEEDL 0x20 //280 clocks
#define ADC_SPEEDH 0x40 //140 clocks
#define ADC_SPEEDHH 0x60 //70 clocks
uchar LEDBuf[35];
uchar gain=6;
uchar Menu=2;
uchar refreshflag[40];
//#include<fft.h>
struct compx
{
float real;
float imag;
};
struct compx dd[65]; //FFT数据
data struct compx temp;
code float 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
};
//复数乘法
void ee(struct compx b1,uchar data 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 data nbottom,uchar data ntop)
{
uint data result=1;
uchar data 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;
}
}
}
//完成显示数据的转换工作,包括顶点下落速度控制以及顶点更新定格
//对fft数据进行处理,得到各个频率段的电压幅值
void processfft(void)
{
uchar data pt=0,tmp;
for(pt=1;pt<65;pt++)
{
dd[pt].imag=0; //清零虚部
}
fft(dd,64); //对当前数据进行傅立叶变换
for(pt=1;pt<65;pt++)
{
dd[pt].real=sqrt(dd[pt].real*dd[pt].real+dd[pt].imag*dd[pt].imag);//取均方根
}
if(Menu==1)
{
for(pt=2;pt<34;pt+=2)
{
for(tmp=(dd[pt].real/32)+1,LEDBuf[pt]=0xFF;tmp>=1;tmp--)//tmp>1;不保留最低位那一行常亮
{
LEDBuf[pt]<<=1;
}
LEDBuf[pt]=~(LEDBuf[pt]);
}
}
else if(Menu==2)
{
//下落感
for(pt=2;pt<34;pt+=2)
{
tmp=(dd[pt].real/32)+1;
if(refreshflag[pt]<tmp) //刷新数据,取较大高度值 存储显示
{
for(LEDBuf[pt]=0xFF;tmp>1;tmp--) //tmp>1;不保留 最低位那一行常亮;{}一次也不执行;
{
LEDBuf[pt]<<=1;
}
refreshflag[pt]=(dd[pt].real/32)+1;
}
else
{
if(refreshflag[pt]>1)refreshflag[pt]--; //顶端下落速度控制 改变值可以改变下降速度
for(LEDBuf[pt]=0xFF,tmp=refreshflag[pt];tmp>1;tmp--) //tmp>1;不保留 最低位那一行常亮
{
LEDBuf[pt]<<=1;
}
}
}
}
else if(Menu==0)
{
//下落感频谱
for(pt=2;pt<34;pt+=2)
{
tmp=(dd[pt].real/32)+1;
if(refreshflag[pt]<tmp) //刷新数据,取较大高度值 存储显示
{
for(LEDBuf[pt]=0xFF;tmp>=1;tmp--)//tmp>1;不保留 最低位那一行常亮;{}一次也不执行;
{
LEDBuf[pt]<<=1;
}
refreshflag[pt]=(dd[pt].real/32)+1;
}
else
{
if(refreshflag[pt]>1)refreshflag[pt]--;
for(LEDBuf[pt]=0xFF,tmp=refreshflag[pt];tmp>=1;tmp--)
{
LEDBuf[pt]<<=1;
}
}
LEDBuf[pt]=~(LEDBuf[pt]);
}
}
}
void delay(uchar t)
{
uchar a=2,j;
while(--a)
{
for(j=t;j>0;j--);
} for(j=t;j>0;j--);
}
void InitADC() //AD初始化
{
ADC_RES = 0; //Clear previous result
ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
delay(10);//ADC power-on and delay
}
uchar GetADCResult(uchar ch)//是几通道就输入几 {
{
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 IOINT()
{
P1ASF=0X03;
P0=0Xff;
P2=0X00;
P3=0X00;
}
void LEDBufrefresh(void)//频谱显示程序
{
uchar data i,x,y;
for(x=1,i=2;x!=0;x<<=1,i+=2)//移位;
{
P2=x;
for(y=1;y!=0;y<<=1)
{
P0=y&LEDBuf[i];
delay(2);
P0=0xff;
}
P2=0x00;
}
for(x=1,i=2;x!=0x80;x<<=1,i+=2)
{
P3=x;
for(y=1;y!=0;y<<=1)
{
P0=y&LEDBuf[i];
delay(2);
P0=0xff;
}
P3=0;
}
}
void time(void)//定时器开启
{
EA=0;
TMOD=0x01;
TH0=0x00;
TL0=0x00;
TR0=1;
ET0=1;
EA=1;
}
void main()
{
uint data Count=700;
uchar data i,Cgain,num=0;
IOINT();
for(i=0;i<=34;i++)
{
LEDBuf[i]=0x00;
}
for(i=0;i<=39;i++)
{
refreshflag[i]=0x09;
}
InitADC();
time();
while(1)
{ for(i=0;i<65;i++)
{
dd[i].real=(GetADCResult(0)+GetADCResult(1))<<gain; //读取ad结果并放大;
}
processfft();//傅立叶变化及处理
if(dd[2].real<32)
{
if(++Count==300) //电平值过小,这降低gain,减少噪音的电平显示;
{
Count=0;
//if(++Menu==4)Menu=0; //切换Menu,显示方式;
gain=6;
}
}
else
{
Count=1;
if(++num==0xAF) //播放时,Auto gain;
{
num=0; //自动增益;Automatic gain;
Cgain=dd[2].real/32;
if(7<Cgain<=8)
{
gain=4;
}
else if(4<Cgain<=6)
{
gain=5;
}
else if(2<Cgain<=4)
{
gain=6;
}
else
{
gain=7;
}
}
}
}
}
void LED() interrupt 1 using 1
{
TR0=0;
LEDBufrefresh();
TL0=0x00;
TH0=0x50;
TR0=1;
根据别人的频谱程序改来的这个程序,他是说要35M的晶振而我手上只有12M的就用了12M的,把延时时间改了一下,但每次运行程序都是满屏的闪烁,看不到频谱,哪位大神帮我看一下,新人,这个问题困惑我好久了!
你可以在网上买个35M的晶振试一下,两者相差太大了,
你的做好了吗?