当前位置:文档之家› adctest - 副本

adctest - 副本


#include "STC12C5A60S2.h"
#include //51基本运算(包括_nop_空函数)
#include

#define uchar unsigned char
#define uint unsigned int
#define ADC_POWER 0x80 //ADC 电源开
#define ADC_SPEED 0x60 // 设为 90 个时钟周期 ADC 一次(40为180周期一次)
#define ADC_START 0x08 //ADC 启动控制位设为开
#define ADC_FLAG 0x10 //ADC 结束标志位
char ch=7;
unsigned int temp_ad[3];
char temp_ad_num=0;//对应temp_ad的计数

uchar data gain=0;
uchar data Menu=2;
uchar LEDBuf [35]; //15列;从左到右;亮的位为真(1);
uchar idata refreshflag[40];
uchar data DelayTime=9; //<=8效果最好;
uchar adnum=0;//fft数据计数变量
char fftflag=0;//fft数据到64标志

struct compx
{
float real;
float imag;
};
struct compx dd[65]; //FFT数据
struct compx temp;


//************************************************//
//******************延时函数************************//
//************************************************//
void delayms( unsigned int nDelay )
{
unsigned int i ;
for( ; nDelay > 0 ; nDelay-- )
{
for( i = 1250; i > 0 ; i-- ) ;
}
}

void adc_init()//片内adc初始化
{
EA=1;
P1ASF=0X80;//P1.7作为信号输入端
ADC_RES=0;
EADC=1;//adc中断
ADC_CONTR=ADC_POWER|ADC_SPEED|ADC_START|ch;//ADC电源开 最快转换速度 启动开 用P1.7作为输入
delayms(1);
}
void io_init()
{
P1M1=0xc3; //p1.7,1.6口高阻做ADC输入
P1M0=0X34;

P3M0=0xff; //P3口推挽输出
P2M0=0xff;

TMOD = 0x11; //高4位控制T/C1 //未用到T0,即0x01
TH1 = (65536-20000)/256;
TL1 = (65536-20000)%256;
ET1 = 1; //T/C1中断开
TR1 = 1; //T/C1启动

// P0M0=0xff;//P0接输入,可以用准双向口
// P0M1=0x00;
}

void Delays(uint t)
{
uint j;
while(--t)
for(j=0;j<5;j++);
}




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 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 data result=1;
uchar data t;
for(t=0;treturn result;
}
//快速傅立叶变换
void fft(struct compx *xin,uchar N)
{
uchar data fftnum,i,j,k,l,m,n,disbuff,dispos,dissec;
data struct compx t;
fftnum=N; //傅立叶变换点数
f

or(m=1;(fftnum=fftnum/2)!=1;m++);//求得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}
for(l=1;l<=m;l++) //FFT运算
{
disbuff=mypow(2,l); //求得碟间距离
dispos=disbuff/2; //求得碟形两点之间的距离
for(j=1;j<=dispos;j++)
for(i=j;i{
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);//取均方根
}

/*
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]);

}

*/
/*
if(Menu==2)
{

//下落感
for(pt=2;pt<34;pt+=2)
{
tmp=(dd[pt].real/32)+1;
if(refreshflag[pt]{
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;
}
}
}
}
*/

{

//下落感频谱
for(pt=2;pt<34;pt+=2)
{
tmp=(dd[pt].real/32)+1;
if(refreshflag[pt]{
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 BufToLED_Refresh() //Refresh&Write Buf to LED ;
{
uchar data i;
uchar data X=1;
uchar data Y=1;
for(X=1,i=2;X;X<<=1,i+=2) //for(X=1;X!=0;X<<=1) //8bit
{
P2=X;
for(Y=1;Y!=0;Y<<=1) //Y=Y<<1;
{
P0=Y&LEDBuf[i];
Delays(DelayTime);
P0=0;
}
P2=0;
};
for(X=1;X<0x80;X<<=1,i+=2) //7bit
{
P3=X;
for(Y=1;Y!=0;Y<<=1) //Y=Y<<1;
{
P0=Y&LEDBuf[i];
Delays(DelayTime);
P0=0;
}
P3=0;
};

}
void main(void)
{
int m,y=0x01;
unsigned char i;//循环变量

adc_init();
io_init();


while(1)
{
fftflag=0;
//if(fftflag==1) processfft();//傅立叶变化及处理
// Led_Refresh();
while(1){
if(fftflag==1)
{
processfft();
fftflag=0;

}
for(i=0;i<16;i+=1)
{
// m = (8*(dd[i].real))/255;//得到在8个灯上的幅度
// m = (0xff<<(m));

P0=LEDBuf[i*2];
if(i<8) {P2=(0x01)<else {P2=0X00;P3=(0x01)<<(i-8);}
}
// BufToLED_Refresh();

}

/*
m = (8*(temp_ad*3))/255;//得到在8个灯上的幅度
m = (0xff<<(m));
P0=m;
*/
}
}

void refresh() interrupt 3
{
int m;
unsigned char i;//循环变量
TH1 = (65536-30000)/256; //0x50~0x80
TL1 = (65536-30000)%256;
//另一种直接显示幅度的方式:全部的灯以一致的幅度显示

/* m = (8*(temp_ad[0]*3))/255;//得到在8个灯上的幅度
m = (0xff<<(m));

P0=m;
P2=0XFF;
P3=0XFF;
*/
/*
//直接采样显示幅度
for(i=0;i<16;i+=1)
{
m = (8*(dd[i*4].real*3))/255;//得到在8个灯上的幅度
m = (0xff<<(m));

P0=m;
if(i<8) {P2=(0x01)<else {P2=0X00;P3=(0x01)<<(i-8);}
}
*/

//显示频谱
for(i=0;i<16;i+=1)
{
// m = (8*(dd[i].real))/255;//得到在8个灯上的幅度
// m = (0xff<<(m));

P0=LEDBuf[i*2];
if(i<8) {P2=(0x01)<else {P2=0X00;P3=(0x01)<<(i-8);}
}

}
void adc_isr() interrupt 5 using 1//adc中断处理
{
int i,m;
EA=0;

ADC_CONTR&=!ADC_FLAG;//ADC_FLAG 软件清0
if(adnum<65&&fftflag==0)
{
dd[adnum].real=(ADC_RES)<<1;//读取的数据放大三倍
adnum++;

}
else
{
adnum=0;
fftflag=1;

}
//用于显示整体幅度的数据存储
/* if(temp_ad_num<4)
{

temp_ad[temp_ad_num]=ADC_RES<<1;
temp_ad_num++;
}
else
{
temp_ad_num=1;

}
temp_ad[0]=sqrt(temp_ad[3]*temp_ad[3]+temp_ad[2]*temp_ad[2]);
*/

ADC_CONTR=ADC_POWER|ADC_SPEED|ADC_START|ch;
EA=1;
}


相关主题
文本预览
相关文档 最新文档