实例介绍
【实例简介】
【实例截图】
【核心代码】
#include "MSP430X14X.h"
#include "math.h"
#include "OCMJ4X8C.h"
#include"MSP430KEY.h"
#include"df_timera.h"
#define num_point 128 //取样点数
#define num_grade 7 //蝶形运算阶数
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 "
"每按一次显示 "
"的功率谱分布显示"
"一个功率值 "
};
unsigned char spectrum[]=
{
" 频谱分析 "
" "
" "
" "
};
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);//大到小的排序
void display(float result[num_point]);
//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;
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;//0-127无符号数序列 频率的参考倍数
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();
AD_timeB(); //定时器控件AD转换
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]; //signed long mem为最初12位无符号采样结果
Chan_data -=0x7FF;
Chan_data *=5;
result[q4] =((float)Chan_data)/4095;//AD转换结果 result=(mem-0x7FF)*5/4095
}
get_power_t(result);
fft(result,tab_dftI);
get_power(result,tab_dftI);
clrram();
chn_disp(Sure);
while(1)
{
key[0]=GetKeyZhi(&key[1]);
if(key[0]==0x88)
goto start;
if(key[0]==0x84)
clrram();
delay(500);
break;
}
clrram();
Clear_GDRAM();
chn_disp(spectrum);
display(result);// 显示频谱
sort(result,count_index); //排序
while(count!=101) //频率为10k
{
key[0]=GetKeyZhi(&key[1]);
if(key[0]==0x88)
goto start;
if(key[0]==0x84)
{
clrram();
Clear_GDRAM();
freq_count =count_index[count]*100; //频率=0
data3=result[count];
data1=(unsigned int)data3; //模,频率对应的整数功率谱
data3=data3-data1; //误差
data2=(unsigned int)(data3*10000); //误差的10000倍(精度小数点后4位有效数字)
Convert(LCD_data,data1,data2,freq_count);
line_disp(LCD_data,0x80);
count ;
freq_count =count_index[count]*100; //频率=
data3=result[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; //200
data3=result[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; //=300
data3=result[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);
count ;
}
}
}
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)第一层 8个级数次循环
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*256/4)
q=p 256/4;
else
q=p-3*256/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 )
{
result[i]=(result[i]*result[i] tab_dftI[i]*tab_dftI[i])/num_point; //取模值,频率对应的功率谱
result[i]=result[i]/num_point;
power_f=power_f result[i]; //频域总功率
}
}
/**************************************************************
系统初始化
**************************************************************/
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; /* ADC12 Start Conversion */
while((ADC12IFG&BIT0)==0);
mem[num_B]=ADC12MEM0; //采样结果赋值给mem
num_B ;
ADC12CTL0&=~ENC;
ADC12CTL0|=ENC;
TBCTL&=~BIT0;
}
/*************************************************************************
定时器控件AD转换
*************************************************************************/
void AD_timeB()
{
ADC12CTL0&=~ENC;
P6SEL |= 0x04; // 使能ADC通道
ADC12CTL0|=REFON REF2_5V SHT0_1 ADC12ON;//SHT0_1 REFON ADC12ON;//多次,2.5vref 使能 SHT0_1设置采样时钟
//for(unsigned iq6=0;iq6<255;iq6 );SHT0_2
ADC12CTL1|=SHP ADC12SSEL_2;//单道1次,clk=mclk=dco SHP要置位 SAMPCON signal is sourced from the sampling timer
ADC12MCTL0 |=INCH_2 SREF_1;
ADC12CTL0|=ENC;//ENC=0才可以改变ADC12CTL1 ADC12CTL2
TBCTL = TBSSEL1 MC0; // MCLK=8MHZ, MC0upmode
TBCCTL0 = CCIE; //允许定时器中断
TBCCR0 = 745; //定时时间
}
/**********************************************************************************
把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; //result=result*25000/4095
value=value/4095;
result=value;
for(unsigned char m=0;m<4;m ) //Figure=[0,0,0,0]
{
Figure[m]=0;
}
for(unsigned char n=0;n<4;n ) //Figure1=[0,0,0,0]
{
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]=(unsigned int)temp;
}
}
}
/////////////////////////////////////////////////////////////
void display(float result[num_point])
{
float result_max=0;
unsigned char count_y;
for(unsigned char m=1;m<61;m ) //绘坐标 y轴
{
GUI_Point(18,m);
if(m%5==0)
GUI_Point(19,m);
}
for(unsigned char n=18;n<num_point-6;n ) //X轴
{ GUI_Point(n,60);
if((n-18)%10==0)
GUI_Point(n,61);}
GUI_Point(17,2);
GUI_Point(19,2);
GUI_Point(120,59);
GUI_Point(120,61);
for(unsigned char k=1;k<num_point;k ) //绘频谱
if(result_max<result[k])
result_max=result[k];
for(unsigned char i=1;i<num_point/2 10;i )
{
count_y=(unsigned char)((result[i]*50)/result_max);
for(unsigned char j=59;j>59-count_y;j--)
GUI_Point(i 18,j);
}
}
好例子网口号:伸出你的我的手 — 分享!
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论