在好例子网,分享、交流、成长!
您当前所在位置:首页C/C++ 开发实例C/C++语言基础 → 电子设计大赛中MSP430写的FFT变换程序(总共128个点)

电子设计大赛中MSP430写的FFT变换程序(总共128个点)

C/C++语言基础

下载此实例
  • 开发语言:C/C++
  • 实例大小:0.16M
  • 下载次数:10
  • 浏览次数:183
  • 发布时间:2019-07-12
  • 实例类别:C/C++语言基础
  • 发 布 人:crazycode
  • 文件格式:.zip
  • 所需积分:2
 相关标签: FFT 设计 程序 大赛

实例介绍

【实例简介】

【实例截图】

from clipboard

【核心代码】

#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); 
  } 
  

 

} 

标签: FFT 设计 程序 大赛

实例下载地址

电子设计大赛中MSP430写的FFT变换程序(总共128个点)

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警