📄 main.c
字号:
#include "MSP430X16X.h"
#include "math.h"
#include "OCMJ4X8C.h"
#include"MSP430KEY.h"
#include"df_timera.h"
#define num_point 256 //取样点数
#define num_grade 8 //蝶形运算阶数
const float tab_sin[256]={
0, 0.0245, 0.0491, 0.0736, 0.0980, 0.1224, 0.1467, 0.1710, 0.1951,
0.2191, 0.2430, 0.2667, 0.2903, 0.3137, 0.3369, 0.3599, 0.3827, 0.4052,
0.4276, 0.4496, 0.4714, 0.4929, 0.5141, 0.5350, 0.5556, 0.5758, 0.5957,
0.6152, 0.6344, 0.6532, 0.6716, 0.6895, 0.7071, 0.7242, 0.7410, 0.7572,
0.7730, 0.7883, 0.8032, 0.8176, 0.8315, 0.8449, 0.8577, 0.8701, 0.8819,
0.8932, 0.9040, 0.9142, 0.9239, 0.9330, 0.9415, 0.9495, 0.9569, 0.9638,
0.9700, 0.9757, 0.9808, 0.9853, 0.9892, 0.9925, 0.9952, 0.9973, 0.9988,
0.9997, 1.0000, 0.9997, 0.9988, 0.9973, 0.9952, 0.9925, 0.9892, 0.9853,
0.9808, 0.9757, 0.9700, 0.9638, 0.9569, 0.9495, 0.9415, 0.9330, 0.9239,
0.9142, 0.9040, 0.8932, 0.8819, 0.8701, 0.8577, 0.8449, 0.8315, 0.8176,
0.8032, 0.7883, 0.7730, 0.7572, 0.7410, 0.7242, 0.7071, 0.6895, 0.6716,
0.6532, 0.6344, 0.6152, 0.5957, 0.5758, 0.5556, 0.5350, 0.5141, 0.4929,
0.4714, 0.4496, 0.4276, 0.4052, 0.3827, 0.3599, 0.3369, 0.3137, 0.2903,
0.2667, 0.2430, 0.2191, 0.1951, 0.1710, 0.1467, 0.1224, 0.0980, 0.0736,
0.0491, 0.0245, 0.0000,-0.0245,-0.0491,-0.0736,-0.0980,-0.1224,-0.1467,
-0.1710,-0.1951,-0.2191,-0.2430,-0.2667,-0.2903,-0.3137,-0.3369,-0.3599,
-0.3827,-0.4052,-0.4276,-0.4496,-0.4714,-0.4929,-0.5141,-0.5350,-0.5556,
-0.5758,-0.5957,-0.6152,-0.6344,-0.6532,-0.6716,-0.6895,-0.7071,-0.7242,
-0.7410,-0.7572,-0.7730,-0.7883,-0.8032,-0.8176,-0.8315,-0.8449,-0.8577,
-0.8701,-0.8819,-0.8932,-0.9040,-0.9142,-0.9239,-0.9330,-0.9415,-0.9495,
-0.9569,-0.9638,-0.9700,-0.9757,-0.9808,-0.9853,-0.9892,-0.9925,-0.9952,
-0.9973,-0.9988,-0.9997,-1.0000,-0.9997,-0.9988,-0.9973,-0.9952,-0.9925,
-0.9892,-0.9853,-0.9808,-0.9757,-0.9700,-0.9638,-0.9569,-0.9495,-0.9415,
-0.9330,-0.9239,-0.9142,-0.9040,-0.8932,-0.8819,-0.8701,-0.8577,-0.8449,
-0.8315,-0.8176,-0.8032,-0.7883,-0.7730,-0.7572,-0.7410,-0.7242,-0.7071,
-0.6895,-0.6716,-0.6532,-0.6344,-0.6152,-0.5957,-0.5758,-0.5556,-0.5350,
-0.5141,-0.4929,-0.4714,-0.4496,-0.4276,-0.4052,-0.3827,-0.3599,-0.3369,
-0.3137,-0.2903,-0.2667,-0.2430,-0.2191,-0.1951,-0.1710,-0.1467,-0.1224,
-0.0980,-0.0736,-0.0491,-0.0245};
//float tab_dftR[num_point]; //输入的波形数据,兼作输出数据的实部
float tab_dftI[num_point]; //输出数据的虚部
float tab_power[num_point]; //模,频率对应的功率谱
float result[num_point]; //AD转换结果
float power_t=0; //时域总功率
float power_f=0; //频域总功率
unsigned int data1;
unsigned int data2;
unsigned char disp1[16];
unsigned char disp2[16];
unsigned int num_B=0;
unsigned int mem[num_point];
//以下为液晶显示信息
unsigned char Text[]=
{
"中山大学 "
"请按E 键开始 "
"音频信号分析仪 "
"按R 键返回 "
};
unsigned char Start[]=
{
"按E 键采集信号 "
"按R 键返回 "
"进行FFT 分析 "
"系统会在5S后返回"
};
unsigned char Sure[]=
{
"请按确定键把FFT "
"每按一次显示 "
"的功率谱分布显示"
"一个功率值 "
};
void InitSys();
void fft(float dataR[num_point],float dataI[num_point]); //FFT变换
void get_power_t(float result[num_point]);//计算时域功率,一定要放于void FFT前,否则result数据被覆盖
void get_power(float result[num_point],float dataI[num_point]); //求模
void AD_timeB();
void AdcConvert(unsigned char *Numeral,unsigned int result);
void sort(float* mod,unsigned int* count_in);//排序
//static unsigned int length;
void main( void )
{
unsigned char key[2],LCD_data[16];
unsigned int count,freq_count;
unsigned long data1,data2;
float data3,data4;
signed long Chan_data;
unsigned int count_index[num_point/2];
WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
for(unsigned int p0=0;p0<num_point/2;p0++)
count_index[p0]=p0;
InitSys();
start:
count=0;
chn_disp (Text);//输出实验人信息
while(1)
{
key[0]=GetKeyZhi(&key[1]);
if(key[0]==0x84)
break;
LPM3;
}
clrram();
chn_disp(Start);
/*
while(1)
{
key[0]=GetKeyZhi(&key[1]);
if(key[0]==0x88)
goto start;
if(key[0]==0x84)
break;
LPM3;
}
clrram();
chn_disp(Signal);
*/
AD_timeB();
while(1)
{
if(num_B==num_point)
{
ADC12CTL0&=~ENC;
TBCTL&=~(BIT5+BIT4);
break;
}
}
for(unsigned int q4=0;q4<num_point;q4++)
{
Chan_data=mem[q4];
Chan_data -=0x7FF;
Chan_data *=5;
result[q4] =((float)Chan_data)/4095;
}
get_power_t(result);
fft(result,tab_dftI);
get_power(result,tab_dftI);
sort(tab_power,count_index);
clrram();
chn_disp(Sure);
while(1)
{
key[0]=GetKeyZhi(&key[1]);
if(key[0]==0x88)
goto start;
if(key[0]==0x84)
break;
}
/*
freq_count =count_index[count]*100;
data3=tab_power[count];
data1=(unsigned int)tab_power[count];
tab_power[count]=tab_power[count]-data1;
data2=(unsigned int)(tab_power[count]*10000);
tab_power[count]=data3;
Convert(LCD_data,data1,data2,freq_count);
line_disp(LCD_data,0x80);
count++;
*/
freq_count =count_index[count]*100;
data3=tab_power[count];
data1=(unsigned int)data3;
data3=data3-data1;
data2=(unsigned int)(data3*10000);
Convert(LCD_data,data1,data2,freq_count);
line_disp(LCD_data,0x80);
count++;
freq_count =count_index[count]*100;
data3=tab_power[count];
data1=(unsigned int)data3;
data3=data3-data1;
data2=(unsigned int)(data3*10000);
Convert(LCD_data,data1,data2,freq_count);
line_disp(LCD_data,0x90);
count++;
freq_count =count_index[count]*100;
data3=tab_power[count];
data1=(unsigned int)data3;
data3=data3-data1;
data2=(unsigned int)(data3*10000);
Convert(LCD_data,data1,data2,freq_count);
line_disp(LCD_data,0x88);
count++;
freq_count =count_index[count]*100;
data3=tab_power[count];
data1=(unsigned int)data3;
data3=data3-data1;
data2=(unsigned int)(data3*10000);
Convert(LCD_data,data1,data2,freq_count);
line_disp(LCD_data,0x98);
while(1);
/*
while(count!=101)
{
key[0]=GetKeyZhi(&key[1]);
if(key[0]==0x88)
goto start;
if(key[0]==0x84)
{
clrram();
tab_power[count]*=10000;
data1=(unsigned int)tab_power[count];
freq_count =count*100;
count++;
Convert(LCD_data,data1,freq_count);
line_disp(LCD_data,0x80);
tab_power[count]*=10000;
data2=(unsigned int)tab_power[count];
freq_count =count*100;
count++;
Convert(LCD_data,data2,freq_count);
line_disp(LCD_data,0x90);
tab_power[count]*=10000;
data3=(unsigned int)tab_power[count];
freq_count =count*100;
count++;
Convert(LCD_data,data3,freq_count);
line_disp(LCD_data,0x88);
tab_power[count]*=10000;
data4=(unsigned int)tab_power[count];
freq_count =count*100;
count++;
Convert(LCD_data,data4,freq_count);
line_disp(LCD_data,0x98);
}
}
*/
}
void get_power_t(float result[num_point])
{
unsigned int i;
for(i=0;i<num_point;i++)
power_t=power_t+result[i]*result[i]/num_point;
}
/*********************************************************
FFT转换
*********************************************************/
void fft(float dataR[num_point],float dataI[num_point])
{
int i,L,j,k,b,p,q,xx,pow1,pow2;
float TR,TI,temp;
/***********following code invert sequence********/
for(i=0;i<num_point;i++)
{
pow1=1;pow2=num_grade-1;
while(pow2>0)
{pow1=pow1*2;pow2--;} // pow1= 2^(pow2)
xx=(i&0x01)*pow1;
for(j=1;j<num_grade;j++)
{
pow1=1;pow2=num_grade-1-j;
while(pow2>0)
{pow1=pow1*2;pow2--;}
xx=xx+((i>>j)&0x01)*pow1;
}
dataI[xx]=dataR[i];
}
for(i=0;i<num_point;i++)
{
dataR[i]=dataI[i];
dataI[i]=0;
}
/********** following code invert sequence ************
//按照书上写的位反转算法
int pp=1,qq;
int bit_rev[num_point];
bit_rev[0]=0;
while(pp<num_point)
{
for(qq=0;qq<pp;qq++)
{
bit_rev[qq]=bit_rev[qq]*2;
bit_rev[qq+pp]=bit_rev[qq]+1;
}
pp=pp*2;
}
for(i=0;i<num_point;i++)
{dataI[i]=dataR[bit_rev[i]];}
for(i=0;i<num_point;i++)
{dataR[i]=dataI[i]; dataI[i]=0;}*/
/************** following code FFT *******************/
for(L=1;L<=num_grade;L++)
{ //for(1)
b=1; i=L-1;
while(i>0)
{b=b*2;i--;} //b= 2^(L-1)
for(j=0;j<=b-1;j++) //for (2)
{
p=1; i=num_grade-L;
while(i>0) //p=pow(2,7-L)*j
{p=p*2;i--;}
p=p*j;
if(p<3*num_point/4)
q=p+num_point/4;
else
q=p-3*num_point/4;
for(k=j;k<num_point;k=k+2*b) //for (3)
{
TR=dataR[k]; TI=dataI[k]; temp=dataR[k+b];
dataR[k]=TR+dataR[k+b]*tab_sin[q]+dataI[k+b]*tab_sin[p];
dataI[k]=TI-dataR[k+b]*tab_sin[p]+dataI[k+b]*tab_sin[q];
dataR[k+b]=TR-dataR[k+b]*tab_sin[q]-dataI[k+b]*tab_sin[p];
dataI[k+b]=TI+temp*tab_sin[p]-dataI[k+b]*tab_sin[q];
} //END for (3)
}//END for (2)
}//END for (1)
}//END FFT
void get_power(float result[num_point],float dataI[num_point])
{
int i;
for(i=0;i<num_point;i++)
{
tab_power[i]=(result[i]*result[i]+tab_dftI[i]*tab_dftI[i])/num_point; //取模值
power_f=power_f+tab_power[i]/num_point;
}
}
/**************************************************************
系统初始化
**************************************************************/
void InitSys()
{
unsigned int iq0;
//使用XT2振荡器
BCSCTL1 &=~XT2OFF; //打开XT2振荡器
do
{
IFG1 &=~OFIFG; //清除振荡器失效标志
for(iq0=0xFF;iq0>0;iq0--);//延时,等待XT2起振
}
while((IFG1&OFIFG)!=0); //判断能力XT2是否起振
BCSCTL2=SELM_2+SELS; //选择MCLK,SMCLK为XT2
InitKey(); //初始化按键端口
TimerAInit(); //初始化定时器A
init_lcd();
_EINT(); //打开全局中断控制,若不需要打开,则可以屏蔽本句
}
/**************************************************************
定时器B中断向量
**************************************************************/
#pragma vector=TIMERB0_VECTOR
__interrupt void Timer_B (void)
{
ADC12CTL0|=ADC12SC;
while((ADC12IFG&BIT0)==0);
mem[num_B]=ADC12MEM0;
num_B++;
ADC12CTL0&=~ENC;
ADC12CTL0|=ENC;
TBCTL&=~BIT0;
}
/*************************************************************************
定时器控件AD转换
*************************************************************************/
void AD_timeB()
{
ADC12CTL0&=~ENC;
ADC12CTL0|=REFON+REF2_5V+SHT0_1+ADC12ON;//SHT0_1+REFON+ADC12ON;//多次,2.5vref 使能
//for(unsigned iq6=0;iq6<255;iq6++);
ADC12CTL1|=SHP+ADC12SSEL_2;//单道1次,clk=mclk=dco SHP要置位
ADC12MCTL0 |=INCH_2+SREF_1;
ADC12CTL0|=ENC;//ENC=0才可以改变ADC12CTL1 ADC12CTL2
TBCTL = TBSSEL1 + MC0; // MCLK, upmode
TBCCTL0 = CCIE; //允许定时器中断
TBCCR0 = 311; //定时时间
}
/**********************************************************************************
把ADC的读数转换为液晶能够显示形式
**********************************************************************************/
void AdcConvert(unsigned char *Numeral,unsigned int result)
{
unsigned int Figure[4],Figure1[4],result1;
unsigned long long value;
result1=result;
value=result;
value=value*25000;
value=value/4095;
result=value;
for(unsigned char m=0;m<4;m++)
{
Figure[m]=0;
}
for(unsigned char n=0;n<4;n++)
{
Figure1[n]=0;
}
for(unsigned char i=5;i>0;i--)
{
Figure[i-1] =result%10;
result=result/10;
}
for(unsigned char j=4;j>0;j--)
{
Figure1[j-1] =result1%10;
result1=result1/10;
}
*Numeral=Figure[0]+48;
Numeral++;
*Numeral='.';
Numeral++;
for(unsigned char k=1;k<5;k++)
{
*Numeral =Figure[k];
*Numeral +='0';
Numeral++;
}
*Numeral='(';
Numeral++;
*Numeral='V';
Numeral++;
*Numeral=')';
Numeral +=2;
for(unsigned char l=0;l<4;l++)
{
*Numeral =Figure1[l];
*Numeral +='0';
Numeral++;
}
}
/****************************************************
排序算法,对tab_mod[]中的数据进行从大到小的排序
***************************************************/
void sort(float* mod,unsigned int* count_in)
{
float temp;
for(unsigned int i=0;i<num_point/2;i++)
for(unsigned int j=i;j<num_point/2;j++)
{
if(mod[i]<mod[j])
{
temp=mod[i];
mod[i]=mod[j];
mod[j]=temp;
temp=count_in[i];
count_in[i]=count_in[j];
count_in[j]=temp;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -