打印
[经验分享]

单片机AD采样,然后FFT变换程序

[复制链接]
2218|50
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ulystronglll|  楼主 | 2023-8-26 19:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用单片机对模拟信号进行转换,转换后做FFT快速傅里叶变换。
#include<math.h>

#define SYSCLK 11000000
#define  PI 3.1415926536
#define  size_x  1024

sfr16 ADC0 = 0xbe;

typedef struct{
     float real;
     float img;
}complex;

complex W[512];
complex xdata x[1024];
float p=0;                                                           //总功率
unsigned int h;

void SYSCLK_Init (void)
{
   int i;                              // delay counter
   OSCXCN = 0x67;                      // start external oscillator with
                                       // 11MHz crystal
   for (i=0; i < 256; i++) ;           // Wait for osc. to start up
   while (!(OSCXCN & 0x80)) ;          // Wait for crystal osc. to settle
   OSCICN = 0x88;                      // select external oscillator as SYSCLK
                                       // source and enable missing clock
                                       // detector
//        OSCICN = 0x07;   //interal 16MHZ
}
void WDT_Init()
{
WDTCN = 0xde;
WDTCN = 0xad;
}
void T3_Init()                                                      //定时48.8us
{
TMR3CN=0x02;
TMR3RLL=(65536-540)%256;
TMR3RLH=(65536-540)/256;
TMR3L=(65536-540)%256;
TMR3H=(65536-540)/256;
TMR3CN|=0X04;                                                          //启动定时器
}
void ADC_Init()
{
AMX0CF=0X00;                                                          //通道0
AMX0SL=0X00;
ADC0CF = (SYSCLK/2500000) << 3;               //SAR时钟为2.5mhz
ADC0CN = 0x84;                                                          //定时器3方式启动
REF0CN = 0x03;
EA=1;
EIE2|=0X02;                    
EIE1&= ~0x04;
}
void ADC0_ISR() interrupt 15
{
ADC0CN&=0xdf;
x[h].real=ADC0;
h++;
}
void add(complex a,complex b,complex *c)
{
     c->real=a.real+b.real;
     c->img=a.img+b.img;
}
void mul(complex a,complex b,complex *c)
{
     c->real=a.real*b.real - a.img*b.img;
     c->img=a.real*b.img + a.img*b.real;
}
void sub(complex a,complex b,complex *c)
{
     c->real=a.real-b.real;
     c->img=a.img-b.img;
}
void change()                                                                                                  //倒位序
{
  unsigned int i=0,j=0,k=0,t;
  complex temp;
  for(i=0;i<size_x;i++)
  {
    k=i;j=0;
        t=(unsigned) (log(size_x)/log(2));
    while(t--)
        {
       j=j<<1;
       j|=(k & 1);                                                                                         
       k=k>>1;
    }
    if(j>i)
        {
       temp=x[i];
       x[i]=x[j];
       x[j]=temp;
    }
  }                                                                                          
}                                                                                                                         //计算旋转因子
void init_W()                                                                                
{
int i;
for(i=0;i<(size_x/2);i++)
{
   W[i].real=cos(2*PI/size_x*i);
   W[i].img=-1*sin(2*PI/size_x*i);
                  
}
}
void FFT()
{
     unsigned int i=0,j=0,k=0,l=0;
     complex up,down;
     change();                                                                                                                          //倒位序
         init_W();                                                                                                                          //计算旋转因子
     for(i=0;i<(int)( log(size_x)/log(2) );i++)                                                          //一级蝶形运算
         {                     
           l=( 1<<i );                                                                                                         
           for(j=0;j<size_x;j+=(1<<(i+1)))                                                                  //一组蝶形运算
                   {                              
                 for(k=0;k<l;k++)
                                 {                                                                                                                  //一个蝶形运算
                                                                     
                        mul(x[j+k+l],W[size_x*k/2/l],&up);
                        add(x[j+k],up,&up);
                        mul(x[j+k+l],W[size_x*k/2/l],&down);
                        sub(x[j+k],down,&down);
                        x[j+k]=up;
                        x[j+k+l]=down;
                 }
           }
     }
}
void PSD()                                                                                             //功率谱
{
unsigned int i;
for(i=0;i<size_x;i++)
{                        
  x[i].real=(1/1024.0)*(x[i].real*x[i].real+x[i].img*x[i].img);
  x[i].img=0;
}
}
void ZP()                                                                                           //总功率
{
  int i;
  for(i=0;i<size_x;i++)
{p+=x[i].real*x[i].real;}
  p=(1/1024.0)*p;
}                                                                                                           //转电压
void ZDY()
{
unsigned int i;
for(i=0;i<1024;i++)
{
  x[i].real=(1/4096.0)*x[i].real*2.4;
}
}
void main()
{
  WDT_Init();
  SYSCLK_Init();
  ADC_Init();
  T3_Init();
  while(h==1024)
  {
   TMR3CN&=0xfb;
   ZDY();
   ZP();
   FFT();
   PSD();
   h=0;
   TMR3CN|=0x04;
  }
}


使用特权

评论回复
沙发
modesty3jonah| | 2023-9-12 16:01 | 只看该作者
采样频率应足够高以捕获所需的信号频率成分,而采样深度决定了采样精度。确保选择的参数在单片机硬件支持的范围内。

使用特权

评论回复
板凳
hearstnorman323| | 2023-9-12 17:11 | 只看该作者
需要选择合适的FFT变换算法,例如快速傅里叶变换(FFT)或离散傅里叶变换(DFT)。

使用特权

评论回复
地板
febgxu| | 2023-9-12 19:27 | 只看该作者
FFT变换是一种快速傅里叶变换算法,可以对数字信号进行频域分析和滤波。

使用特权

评论回复
5
sdCAD| | 2023-9-13 10:49 | 只看该作者
在进行AD采样时,需要注意采样速率、采样位数和采样范围等参数,以确保采样结果的准确性。

使用特权

评论回复
6
youtome| | 2023-9-13 11:09 | 只看该作者
对于模拟信号,需要使用模拟信号数据类型;对于数字信号,需要使用数字信号数据类型。

使用特权

评论回复
7
juliestephen| | 2023-9-13 11:58 | 只看该作者
选择合适的FFT算法以满足性能和资源要求。常见的FFT算法包括快速傅里叶变换(FFT)和快速**玛变换(FHT)。根据单片机的处理能力和存储空间,选择适当的算法和优化策略。

使用特权

评论回复
8
deliahouse887| | 2023-9-13 12:26 | 只看该作者
在使用ADC时,需要注意不要超出芯片的测量范围和存储容量;在使用FFT算法时,需要注意不要超出芯片的计算能力。

使用特权

评论回复
9
lzmm| | 2023-9-13 14:10 | 只看该作者
单片机系统中的电源稳定性和噪声抑制也是关键因素。

使用特权

评论回复
10
ingramward| | 2023-9-13 16:36 | 只看该作者
采样数据可以是实数或复数形式,根据需要选择合适的数据格式。在进行FFT变换之前,可能需要进行预处理

使用特权

评论回复
11
geraldbetty| | 2023-9-13 17:20 | 只看该作者
考虑到可能出现的错误和异常情况,设计适当的错误处理机制,以确保系统的稳定性和可靠性。

使用特权

评论回复
12
biechedan| | 2023-9-13 18:04 | 只看该作者
可能需要采取一些措施来减少干扰,比如使用屏蔽材料,或者在电路板设计时考虑到电磁兼容性

使用特权

评论回复
13
olivem55arlowe| | 2023-9-13 18:12 | 只看该作者
对FFT变换结果进行处理,例如进行数据滤波、数据压缩等。

使用特权

评论回复
14
ccook11| | 2023-9-13 18:28 | 只看该作者
考虑噪声源、信号处理和滤波技术,以提高信噪比和减小噪声对FFT结果的影响。

使用特权

评论回复
15
janewood| | 2023-9-13 18:44 | 只看该作者
选择合适的FFT变换数据类型,例如浮点数或定点数。

使用特权

评论回复
16
wengh2016| | 2023-9-13 19:04 | 只看该作者
在进行FFT变换之前,通常需要对采样数据进行预处理,如去直流分量、滤波等。这可以帮助提高FFT的准确性和性能。

使用特权

评论回复
17
lzmm| | 2023-9-13 21:07 | 只看该作者
在进行FFT变换时,需要注意输入信号的格式和大小,以确保变换结果的准确性。

使用特权

评论回复
18
10299823| | 2023-9-13 21:16 | 只看该作者
选择适用于你的单片机平台的FFT库或实现FFT算法

使用特权

评论回复
19
modesty3jonah| | 2023-9-13 21:24 | 只看该作者
应该使用一个抗混叠滤波器来过滤掉高于采样率一半的频率成分。

使用特权

评论回复
20
everyrobin| | 2023-9-13 22:57 | 只看该作者
FFT变换后的结果通常是频谱图或功率谱密度图。根据需要,可以对结果进行幅度谱、相位谱、频率分析等进一步处理和显示。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

1207

帖子

1

粉丝