实例介绍
【实例简介】
【实例截图】
【核心代码】
#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小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论