搜索
bottom↓
回复: 168

实践“玩转FFT算法...任你移植”,正确AD采样及生成函数表

  [复制链接]

出0入0汤圆

发表于 2014-12-26 23:53:05 | 显示全部楼层 |阅读模式
本帖最后由 nos002 于 2014-12-27 00:56 编辑

   
    本人是个懒人,对于FFT算法,受水平限制自己是无论如何也理解不透,更写不出算法代码。好在有很多大神无私分享他们的成果,使得很多人站在大神的肩上(熟知的是巨人的肩上,好像不对,怎么能站到大神的肩上呢)忙碌自己的东西。
言归正传。最近手头有个东西需要显示交流电压和电流有效值,原本用的均方根法倒也简单,但硬件上没设过零检测无法自适应频率,于是搜了一通FFT测频,结果到了这里。虽然没找到测频的方法,但实践一下FFT测交流信号有效值也颇有兴趣。交流电压采样输入如下图:

输入波形不是很光滑,ADC为MCU的10位ADC,一周期采样64点。
搬运了海涵大神帖里的FFT代码,仔细阅读了相关注释,使用正弦函数生产软件生成了64点整数型正弦和余弦函数表。AD转换存入Fft_Real[]的数据为ADC的采样值减去直流电平值的绝对值。利用FFT计算的结果取基波Fft_Real[1]和Fft_Image[1]数据平方和后开根号,即基波的幅值,结果数据是随机的。生成64点全波正整形函数表,结果依然随机,百般折腾无果。没能力自己写出算法代码,只能充分信任搬运的了(╮(╯▽╰)╭)。
   
     静下心来仔细看了几遍代码,发现FFT代码只取函数表的前半部的表值,尝试修改一些表达式以使能够取到全部表值,结果Fft_Real[]数据乱飞更凌乱了。分析整形正弦函数表前半部表值为正后半部表值为负,而代码只取前半部表值,算法思想应该是正、余弦波正负半波对称,那么要计算整个一周期的正、余弦函数,AD采样值就应该是一周波形的数据,而不是绝对值。据此修改了AD采样代码,正、余弦函数表采用32点半周整形数据。代码运行结果是基波幅值基本恒定。10位ADC量程700V,由于平移为单极性信号,使得ADC的分辨率降低一半,即只有700/512 V,代码运算结果取20次平均值后在正负1V跳动。只是FFT运算的幅值是实际的输入波形幅值的5倍,疑惑中,望高手解答!
此实践经验小结给同样的疑惑的电工,本人知识浅陋比较业余,高手见笑。

代码运行的硬件平台为PIC24FKL402,原样搬运的代码如下:
  1. /**********************************************************************************************************************************************
  2. * 这里讲讲傅立叶快速变换FFT算法的C例程,不恰当的地方还请探讨。
  3. * 此例程可以移植到任何的单片机,但前提是单片机内存要够大(如果做32点的应该256字节内存就足够了),至于速度快或慢,只要你能承受那些慢速的就无所谓。
  4. * 这里以128点采样作为例子。要注意的是,采样点数N和采样率Fs还有信号频率F的关系。
  5. * FFT算法可以把对波形采样回来的数据进行转换,比如有一个模拟信号过来,假设对其以某个采样率采样了128个点的数据,经过FFT换算以后,就可以获得这段
  6. * 波形里面含有的不同频率的特征,也就是变成频谱。换算的结果是以复数的形式表现的,比如某个频率的信息以a+bi的形式表示,这里a是实部,b是虚部。
  7. * 而例程中会以数组s16 Fft_Real[128]来表示128个频率的实部,以s16 Fft_Image[128]来表示128个频率的虚部。
  8. * 采样点数N和采样率Fs还有信号频率F的关系是这样的,在一个模拟信号中,采样率至少应该是这个信号中需要分析的最高频率的2倍,而这个信号中需要分析的
  9. * 最低频率Fl=Fs/N,也就是采样率除以采样点数,同时这个频率也是fft换算过程的频率分辩率。可能有点晕了,这里举例说明。
  10. * 假设我们有一个信号里面含有100Hz的信号和含有1000Hz的信号叠加在一起,用示波器是很难分清的,通过对这信号进行采样和FFT转换就可以得到这组信号的
  11. * 频谱特征,因为需要分析的最低信号为100Hz,我们假设现在对信号要进行128点的采样,那么我们至少要能分辨100Hz的信号,采样率可以是100Hzx128点=12800Hz,
  12. * 也就是我们需要以每秒采集12800点的速度来采集1/100秒的时间(因为只采集128点,所以时间上是1/100秒),当然也可以使用6400Hz的采样率,这样分辩率是50Hz,
  13. * 这里就以12800Hz为例。
  14. * 采集回来的数据要怎么处理呢?首先对于FFT算法,需要有数组数据输入,经过FFT换算以后会以数组数据输出。我们可以直接定义两个数组s16 Fft_Real[128]和
  15. * s16 Fft_Image[128],我们把采集来的128个数据按一个特殊的顺序输入到s16 Fft_Real[128]这个数组里面(当作实部输入),而s16 Fft_Image[128]则全部输入0,
  16. * 然后运行fft算法转换。转换过后,s16 Fft_Real[128]里面的128个数会变成128个频率的实部,而s16 Fft_Image[128]里面的128个数会变成128个频率的虚部。
  17. * 哪128个频率呢,实际上只能获得64个频率。在这两个输出的数组里面,数组s16 Fft_Real[128]的第一个数(第一个数是s16 Fft_Real[0])和s16 Fft_Image[128]
  18. * 的第一个数(第一个数是s16 Fft_Image[0])分别是0Hz这个频率的复数形式结果里面的实部和虚部,而第二个数是100Hz的复数形式的结果,第三个数是200Hz的结果,
  19. * 依此类推,第64个数是6300Hz的结果。假如我们想知道信号中是否含有100Hz这个频率存在,那么我们需要查看s16 Fft_Real[1]和s16 Fft_Image[1]这两个数,
  20. * 把实部和虚部分别进行平方求和以后再开平方,就是100Hz信号的模,把模值除以采样点数N的1/2就得到100Hz的信号的峰值。同理,要知道信号里面是否含有1000Hz,
  21. * 我们需要取出s16 Fft_Real[10]和s16 Fft_Image[10]来计算。这128组数据里面,只有前面64组是有用的,后面的都是镜像数据,我们不理会。因为采样率是12800Hz,
  22. * 我们能查看的最高频率是6400Hz,也就是需要拿s16 Fft_Real[64]和s16 Fft_Image[64]出来算,但这两个值很可能不再准确,因为是极限的问题。
  23. *
  24. * 以下我们来看看相关的例程,这个例程可以用于移植到任何的单片机中,只要单片机的速度不太慢(太慢你愿意慢慢等也没关系),内存足够就可以运行。这个例程可以
  25. * 修改为256点和512点或者1024点甚至更高点数的fft,下面会讲到需要修改一些什么参数。增加采样点数可以在采样率不变的情况下增加分辩率,如果点数增加一倍,
  26. * 采样率也提高一倍,那么分辩率不变,但能识别的最高频率将提高一倍,这是采样点数增加的好处,但同时会减慢运算速度。此例程使用stm32f103在72M主频下测试256点fft,
  27. * 运算时间为10mS左右,官方的函数库不知道会不会经过优化而更快,但考虑到许多人不喜欢使用函数库,也考虑这个例程的可移植性,这里直接使用fft函数而不讲函数库的内容。
  28. *********************************************************************************************************************************************/

  29. #include<p24Fxxxx.h>
  30. #include<math.h>
  31. #include<stdlib.h>
  32. #include"GenericTypeDefs.h"

  33. #define NUM_FFT 64  //这里要算多少点的fft就赋值多少,值只能是2的N次方
  34. #define N       6   //这里因为128是2的7次方,如果是计算256点,则是2的8次方,N就是8,如果是512点则N=9,如此类推

  35. //以下为FFT傅立叶转换算法用到的相关定义
  36. //UINT8 ADC_Count = 0;
  37. /********注意,这里u8就是8位的unsigned char类型数据,在51里面就是unsigned char。以下的数组s16 Fft_Real[128]就是16位signed类型的数组,相当于signed int,
  38. * 而Fft_Real只是一个数组的名字,随便起也可以的,Fft_Image也一样**********/

  39. //这是用到的一些寄存器,注意这里如果要算256点以上的fft的话,需改成16位的u16。

  40. //中间临时变量,名称也是自己定义的,但要与fft函数里面的对应

  41. //UINT16 TEMP1; //用于求功率的,可不需要
  42. INT16 Fft_Real[NUM_FFT]; //fft实部,128数组
  43. INT16 Fft_Image[NUM_FFT]; //fft虚部,128数组
  44. UINT8 FFTSwitch = 0;
  45. UINT8 CalculateSW = 0;
  46. float Vrms;

  47. void Fft_Imagclear(void);

  48. /*********************************************************************************************************************************
  49. * 以下为放大128倍后的sin正弦函数数组表格,这个表格可以用“正弦波表生成”这个软件来生成,要注意需要做多少点的fft,就需要生成多少点的。
  50. * 数据类型要选择整形,不要选择正整型,这里为了能在普通单片机快速运行,不使用浮点数,使用查表法以达到最快的运算。如果是256点以上的,表格
  51. * 数据类型s8要改成s16的,以下的两个数组表格也同样如此,注意这里相当于指针用法,如果内存足够的,最好把表格写入内存,那样运行速度快,如果
  52. * 内存资源紧的,就把表格写入程序区,对于51就是一个signed char code table[N]和signed char table[N]的区别,带了code就告诉编译器我这个表
  53. * 格要放在ROM程序存储区,不带code就直接放入内存,其他单片机不同写法自己研究研究
  54. *
  55. * *******************************************************************************************************************************/
  56. const INT8 SIN_TAB[32] = {0x00, 0x0c, 0x18, 0x24, 0x30, 0x3b, 0x46, 0x50,
  57.                           0x59, 0x62, 0x69, 0x70, 0x75, 0x79, 0x7c, 0x7e,
  58.                           0x7f, 0x7e, 0x7c, 0x79, 0x75, 0x70, 0x69, 0x62,
  59.                           0x59, 0x50, 0x46, 0x3b, 0x30, 0x24, 0x18, 0x0c};

  60. //以下是放大128倍后的cos余弦函数数组表格,这里注意事项与上面相同,只不过选择余弦来生成
  61. const INT8 COS_TAB[32] = {0x7f, 0x7e, 0x7c, 0x79, 0x75, 0x70, 0x69, 0x62,
  62.                           0x59, 0x50, 0x46, 0x3b, 0x30, 0x24, 0x18, 0x0c,
  63.                           0x00, -0x0c, -0x18, -0x24, -0x30, -0x3b, -0x46, -0x50,
  64.                           -0x59, -0x62, -0x69, -0x70, -0x75, -0x79, -0x7c, -0x7e};

  65. /************************************************************************************************************
  66. * 以下是采样存储序列表,这个表格可以在FFT_Code_Tables.h这个文件里面找到,更多点的FFT也在里面找,就是里面的unsigned
  67. * int code BRTable[N]的那些,是用来控制采样点数据输入到实部数组s16 Fft_Real[128]里面的
  68. ************************************************************************************************************/
  69. const UINT8 LIST_TAB[64] = {
  70.                             0, 32, 16, 48, 8, 40, 24, 56,
  71.                             4, 36, 20, 52, 12, 44, 28, 60,
  72.                             2, 34, 18, 50, 10, 42, 26, 58,
  73.                             6, 38, 22, 54, 14, 46, 30, 62,
  74.                             1, 33, 17, 49, 9, 41, 25, 57,
  75.                             5, 37, 21, 53, 13, 45, 29, 61,
  76.                             3, 35, 19, 51, 11, 43, 27, 59,
  77.                             7, 39, 23, 55, 15, 47, 31, 63
  78. };

  79. /********************************************************************************************************************************
  80. * 以下为fft算法主体部分
  81. * ******************************************************************************************************************************/

  82. void FFT(void)
  83. {
  84.     UINT8 i, j, k, b, p;
  85.     INT16 Temp_Real, Temp_Imag, temp;
  86.     UINT16 Max, Min;
  87.     UINT32 sum;
  88.     static UINT16 Count = 0;
  89.     static UINT16 Vpeak[30];

  90.     if (FFTSwitch == 1)
  91.     {
  92.         Fft_Imagclear();
  93.         for (i = 1; i <= N; i++) /* for(1) */
  94.         {
  95.             b = 1;
  96.             b <<= (i - 1); //蝶式运算,用于计算 隔多少行计算。例如第一级 1和2行计算,,,第二级
  97.             for (j = 0; j <= b - 1; j++) /* for (2) */
  98.             {
  99.                 p = 1;
  100.                 p <<= (N - i);
  101.                 p = p*j;
  102.                 for (k = j; k < NUM_FFT; k = k + 2 * b) /* for (3) 基二fft */
  103.                 {
  104.                     Temp_Real = Fft_Real[k];
  105.                     Temp_Imag = Fft_Image[k];
  106.                     temp = Fft_Real[k + b];
  107.                     Fft_Real[k] = Fft_Real[k] + ((Fft_Real[k + b] * COS_TAB[p]) >> 7) + ((Fft_Image[k + b] * SIN_TAB[p]) >> 7);
  108.                     Fft_Image[k] = Fft_Image[k] - ((Fft_Real[k + b] * SIN_TAB[p]) >> 7) + ((Fft_Image[k + b] * COS_TAB[p]) >> 7);
  109.                     Fft_Real[k + b] = Temp_Real - ((Fft_Real[k + b] * COS_TAB[p]) >> 7) - ((Fft_Image[k + b] * SIN_TAB[p]) >> 7);
  110.                     Fft_Image[k + b] = Temp_Imag + ((temp * SIN_TAB[p]) >> 7) - ((Fft_Image[k + b] * COS_TAB[p]) >> 7);
  111.                     //移位,防止溢出。结果已经是本值的1/64
  112.                     Fft_Real[k] >>= 1;
  113.                     Fft_Image[k] >>= 1;
  114.                     Fft_Real[k + b] >>= 1;
  115.                     Fft_Image[k + b] >>= 1;
  116.                 }
  117.             }
  118.         }
  119.         Vpeak[Count++] = (UINT16)(100 * sqrt(Fft_Real[1] * Fft_Real[1] + Fft_Image[1] * Fft_Image[1]));
  120.         if (Count == 30)
  121.         {
  122.             sum = 0;
  123.             Max = Vpeak[0];
  124.             Min = Vpeak[0];
  125.             for (i = 0; i < Count; i++)
  126.             {
  127.                 if (Vpeak[i] > Max)
  128.                     Max = Vpeak[i];
  129.                 if (Vpeak[i] < Min)
  130.                     Min = Vpeak[i];
  131.                 sum += Vpeak[i];
  132.             }
  133.             Vrms = (sum - Max - Min)/ (Count - 2);
  134.             Vrms = Vrms / 32 /1.414;
  135.             Count = 0;
  136.         }
  137.         FFTSwitch = 0;
  138.     }
  139.     //         Fft_Real[0]=Fft_Image[0]=0;  //去掉直流分量,也可以不去掉
  140.     //   Fft_Real[63]=Fft_Image[63]=0;
  141.     //以上已经把128点的实部和虚部求完,下一次运算前需要把所有虚部重新清零。
  142.     //要求某个频率点的模,则模值=根号(实部平方+虚部平方),即sqrt((Fft_Real[n]*Fft_Real[n])+(Fft_Image[n]*Fft_Image[n])),
  143.     //第n个频率点的值是数组上的Fft_Real[n]和Fft_Image[n],而Fft_Real[0]是直流分量。Fft_Real[1]是最低频率点,也是最小频率分辩率值,等于采样率/采样点数N。
  144.     //波形峰值大小=模值/(N/2), N为采样点数。
  145.     //注意,由于上面把求得的值已经移位除法,相当于缩小了64倍(移位7位好像是128倍吧??后面为什么还要移动一位?这里待高手指点,本人也不是很清楚,这里只做移植总结)。
  146.     //得到的那些实部虚部的结果爱怎么处理怎么处理,可以做音频频谱强度显示啦什么的。
  147. }

  148. /************************************************************************************************************************************
  149. *
  150. ************************************************************************************************************************************/
  151. void Fft_Imagclear(void) //fft虚部清零函数,在运行FFT函数之前需要先运行这个
  152. {
  153.     volatile UINT8 cnt;
  154.     for (cnt = 0; cnt < NUM_FFT; cnt++)
  155.     {
  156.         Fft_Image[cnt] = 0;
  157.     }
  158. }

  159. // 以下是和MCU硬件相关的部分

  160. /********************************************************************************************
  161. * 模 块:ADC初始化
  162. ********************************************************************************************/
  163. void ADC_Init(void)
  164. {
  165.     ANSA |= 0x0002; // RA1为模拟输入
  166.     TRISA |= 0x0002;
  167.     AD1CON1 = 0x0000;
  168.     AD1CON2 = 0x0000;
  169.     AD1CON3 = 0x0000;
  170.     AD1CHS = 0x0000;
  171.     AD1CSSL = 0x0000;


  172.     AD1CON1bits.SSRC = 0b010; // 由Timer1 比较结束采样并启动转换
  173.     AD1CON1bits.ASAM = 1; // 1 = 最后一次转换结束后立即开始采样; SAMP 位自动置1
  174.     AD1CON1bits.ADSIDL = 1;

  175.     AD1CON2bits.VCFG = 0b000; // VREF+接AVDD,VREF-接AVSS
  176.     AD1CON2bits.OFFCAL = 0; // 获取实际值
  177.     AD1CON2bits.CSCNA = 0; // 不扫描输入
  178.     AD1CON2bits.SMPI = 0b0000; // 每完成1个采样产生中断
  179.     AD1CON2bits.ALTS = 0; // 总是使用MUX A输入多路开关设置

  180.     AD1CON3bits.ADCS = 0b00001; // 转换时钟 2TCY
  181.     AD1CON3bits.SAMC = 0b00100; // 自动采样时间 8*TAD

  182.     AD1CHSbits.CH0SA = 1; // 选择AN1
  183.     AD1CHSbits.CH0NA = 0;

  184.     IPC3bits.AD1IP = 0b011;
  185.     IEC0bits.AD1IE = 1;
  186.     IFS0bits.AD1IF = 0;
  187.     AD1CON1bits.ADON = 1; //打开AD模块

  188. }

  189. /**************************************************************
  190. * 模 块:TIMER1初始化
  191. ***************************************************************/
  192. void T1_Init(void)
  193. {
  194.     TMR1 = 0;
  195.     PR1 = (UINT16)((16129.0/SAMPLE_POINTS)/Tcy); //5000 = (20ms*1000/64)/0.0625
  196.     T1CONbits.TCS = 0; //内部时钟,Fosc/2
  197.     T1CONbits.TCKPS = 0b00; //预分频 1:1
  198.     T1CONbits.TGATE = 0; //0 = 禁止门控时间累加
  199.     IPC0bits.T1IP = 0b011;
  200.     IFS0bits.T1IF = 0;
  201.     //IEC0bits.T1IE = 1;
  202.     T1CONbits.TON = 1;

  203. }

  204. /*************************************************************************************
  205. * 模 块:TIMER1
  206. * 用 途:用于结束ADC采样并启动转换,由ADC1CON1设置
  207. *************************************************************************************/
  208. void __attribute__((interrupt, shadow, no_auto_psv)) _T1Interrupt()
  209. {
  210.     IFS0bits.T1IF = 0; // manually cleared MI2C1 Interrupt flag

  211. }
  212. /*************************************************************************************
  213. * 模 块:ADC中断
  214. * 用 途:每中断一次读取一个采样点的瞬时值
  215. *************************************************************************************/
  216. extern UINT8 FFTSwitch;
  217. void __attribute__((interrupt, shadow, no_auto_psv)) _ADC1Interrupt(void)
  218. {
  219.     static UINT8 i = 0,j = 0;

  220.     IFS0bits.AD1IF = 0;
  221.     SampleBuf[i++] = ADC1BUF0;
  222.     if (SAMPLE_POINTS == i)
  223.     {
  224.         i = 0;
  225.         SampleCycleMsg = 1;
  226.     }
  227.     if(FFTSwitch == 0)
  228.     {
  229.         Fft_Real[LIST_TAB[j++]] = ADC1BUF0 - MEDIAN_VREF; // ADC采样值 - 参考电压半值,即得到交流采样信号的正负半波瞬时值
  230.         if (SAMPLE_POINTS == j)
  231.         {
  232.             j = 0;
  233.             FFTSwitch = 1;
  234.         }
  235.     }
  236. }


复制代码


海涵原帖代码及完整代码出处:https://github.com/bjornfor/barcode_finder



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2014-12-27 00:10:48 来自手机 | 显示全部楼层
沙发,赞一个!

出0入0汤圆

发表于 2014-12-27 01:49:13 | 显示全部楼层
赞一个。

出0入0汤圆

发表于 2014-12-27 07:22:41 来自手机 | 显示全部楼层
好帖,慢慢品读

出0入0汤圆

发表于 2014-12-27 07:59:15 | 显示全部楼层
收藏了,谢谢

出0入0汤圆

发表于 2014-12-27 08:29:40 来自手机 | 显示全部楼层
学习,谢谢分享

出0入0汤圆

发表于 2014-12-27 08:47:58 来自手机 | 显示全部楼层
谢谢分享啦!

出0入0汤圆

发表于 2014-12-27 09:18:42 | 显示全部楼层
好资料呀  留下来慢慢学习

出0入0汤圆

发表于 2014-12-27 09:45:11 | 显示全部楼层
支持下...

出0入0汤圆

发表于 2014-12-27 09:49:00 | 显示全部楼层
好东西,有空好好学习

出0入0汤圆

发表于 2014-12-27 10:31:19 | 显示全部楼层
挺好的。

出100入101汤圆

发表于 2014-12-27 14:25:59 | 显示全部楼层
难得看到用PIC24单片机的。LZ能不能帮忙看下这个帖子中的问题,http://www.amobbs.com/thread-5609469-1-1.html

出0入0汤圆

发表于 2014-12-27 16:27:11 | 显示全部楼层
不错的基础知识,学习了!

出0入0汤圆

发表于 2014-12-31 09:30:59 | 显示全部楼层
fft都忘的差不多了,得好好回忆一下了

出0入0汤圆

发表于 2014-12-31 09:47:48 | 显示全部楼层
这个先收藏,用到时好好看看

出0入0汤圆

发表于 2014-12-31 09:56:28 | 显示全部楼层
mark,收藏后细看

出0入0汤圆

发表于 2014-12-31 10:27:21 来自手机 | 显示全部楼层
正想学习fft,楼主就送来了。感谢!

出0入36汤圆

发表于 2014-12-31 12:41:23 | 显示全部楼层
收藏,等用的时候就方便了,谢谢~

出0入0汤圆

发表于 2014-12-31 13:09:21 | 显示全部楼层
技术贴,搜藏+支持

出0入0汤圆

发表于 2014-12-31 13:12:55 | 显示全部楼层
很好的资料,楼主费心了,需要慢慢的研究

出0入0汤圆

发表于 2014-12-31 14:43:17 | 显示全部楼层
不错,以后肯定用得到,收了

出0入0汤圆

发表于 2014-12-31 16:31:55 | 显示全部楼层
用STM32做FFT速度够么?

出0入0汤圆

发表于 2014-12-31 16:35:43 | 显示全部楼层
说的太棒了!顶!!!

出0入0汤圆

发表于 2014-12-31 17:16:31 | 显示全部楼层
分析很透彻~

出0入0汤圆

发表于 2014-12-31 20:42:32 来自手机 | 显示全部楼层
好帖,好好学习。

出0入0汤圆

发表于 2015-1-1 19:30:16 | 显示全部楼层
st有自己的官方库的,还是1024点,效率比较高,不过其单片机用这移植方便

出0入0汤圆

发表于 2015-1-2 10:14:57 来自手机 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2015-1-2 13:32:43 | 显示全部楼层
非常好的帖子  学习了

出0入0汤圆

发表于 2015-1-2 14:38:34 | 显示全部楼层
很不错的资料,谢谢各位大神的分享

出0入0汤圆

发表于 2015-1-2 14:55:36 | 显示全部楼层
好东西,强烈支持。

出0入0汤圆

发表于 2015-1-2 16:27:25 | 显示全部楼层
赞一个,最近在看FFT方面的东西,感谢lz分享。
另,lz的注释好详细呀。

出0入0汤圆

发表于 2015-1-2 16:42:47 | 显示全部楼层
代码好整齐。

出0入53汤圆

发表于 2015-1-2 17:00:38 | 显示全部楼层
谢谢lz分享

出675入8汤圆

发表于 2015-1-2 22:23:45 | 显示全部楼层
fft不能测频吗?

出675入8汤圆

发表于 2015-1-2 22:24:27 | 显示全部楼层
FFT不能用来测频吗?

出0入0汤圆

发表于 2015-1-2 22:42:43 | 显示全部楼层
谢谢分享,

出0入0汤圆

发表于 2015-1-2 23:43:25 | 显示全部楼层
好帖,慢慢品读

出0入0汤圆

发表于 2015-2-16 15:47:03 | 显示全部楼层
顶一个...

出0入0汤圆

发表于 2015-2-16 16:23:36 来自手机 | 显示全部楼层
支持一下,用得着

出0入0汤圆

发表于 2015-2-17 23:37:13 | 显示全部楼层
谢谢分享!很不错的资料!

出0入0汤圆

发表于 2015-2-18 08:50:23 来自手机 | 显示全部楼层
先收藏,以后在慢慢看

出0入0汤圆

发表于 2015-2-18 09:07:19 | 显示全部楼层
mark 好贴!!!!!!!!!!!!!!

出0入0汤圆

发表于 2015-2-18 10:12:35 | 显示全部楼层
我也很想理解下fft,但是理论不过关

出0入0汤圆

发表于 2015-2-18 11:28:16 | 显示全部楼层
谢谢大神  正要学习呢

出0入0汤圆

发表于 2015-2-18 12:50:19 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2015-2-18 13:15:27 | 显示全部楼层
好帖,代码讲的很详细啊

出0入0汤圆

发表于 2015-2-18 13:37:29 | 显示全部楼层
厉害啊,FFT讲解的很透彻,有空顺便学习下

出0入0汤圆

发表于 2015-2-18 15:05:12 来自手机 | 显示全部楼层
用过别人写的fft,一直没静下来仔细看过

出50入0汤圆

发表于 2015-2-21 14:35:01 | 显示全部楼层
假如我们想知道信号中是否含有100Hz这个频率存在,那么我们需要查看s16 Fft_Real[1]和s16 Fft_Image[1]这两个数,
* 把实部和虚部分别进行平方求和以后再开平方,就是100Hz信号的模,把模值除以采样点数N的1/2就得到100Hz的信号的峰值。
根据注释,要测频率的实质就是看相应频率的幅值,〉0应该是存在这个频率,幅值越大,相应频率的信号就越强。
其实LZ已经测得了频率了~~~哈哈
多次遭遇FFT,但是直到现在仔细 看了下本帖的注释后才知道,这东东真的主营频谱分析

出0入0汤圆

发表于 2015-2-22 12:06:16 来自手机 | 显示全部楼层
好帖

出10入95汤圆

发表于 2015-2-23 13:01:54 | 显示全部楼层
多谢分享1!!

出0入0汤圆

发表于 2015-2-23 13:27:27 | 显示全部楼层
收藏  学学

出0入0汤圆

发表于 2015-2-23 14:37:02 | 显示全部楼层
正想学习FFT的实际使用,先看看

出0入0汤圆

发表于 2015-2-23 22:47:52 | 显示全部楼层
这个收藏了,好贴

出0入0汤圆

发表于 2015-2-24 02:25:12 | 显示全部楼层
支持好贴。

出0入0汤圆

发表于 2015-2-24 06:31:26 来自手机 | 显示全部楼层
支持好帖,辛苦

出0入0汤圆

发表于 2015-2-24 11:39:34 | 显示全部楼层
to LZ : 搜索一下 频谱泄露 和 栅栏效应 , 你会学得更多..

出0入0汤圆

发表于 2015-2-27 13:39:48 | 显示全部楼层
非常感谢!!!

出0入0汤圆

发表于 2015-3-9 11:25:06 | 显示全部楼层
Mark!

出0入0汤圆

发表于 2015-3-9 12:55:25 | 显示全部楼层
多谢分享!!!!

出0入0汤圆

发表于 2015-3-9 13:03:34 | 显示全部楼层
值得收藏,后面慢慢看

出0入0汤圆

发表于 2015-3-10 01:12:03 | 显示全部楼层
一到了主要算法那里就不懂了- -

出0入0汤圆

发表于 2015-3-10 08:34:49 | 显示全部楼层

出0入0汤圆

发表于 2015-3-10 08:59:44 | 显示全部楼层
解释的很清楚, 不错, mark一下

出0入0汤圆

发表于 2015-3-10 09:11:45 | 显示全部楼层
再加个窗函数应用就更广泛了

出0入0汤圆

发表于 2015-3-11 10:42:15 | 显示全部楼层
最近这么多人研究FFT啊

出0入0汤圆

发表于 2015-3-11 10:49:22 | 显示全部楼层
好东西,学习了

出0入0汤圆

发表于 2015-3-12 08:29:48 | 显示全部楼层
好东西,收藏下

出0入0汤圆

发表于 2015-3-12 08:39:48 | 显示全部楼层
好东西,回头研究下

出0入0汤圆

发表于 2015-3-12 12:16:38 | 显示全部楼层
MARK 用到再来看

出0入0汤圆

发表于 2015-4-18 17:30:06 | 显示全部楼层
赞一个

出0入0汤圆

发表于 2015-4-18 18:18:50 | 显示全部楼层
谢谢分享,收藏学习下

出0入0汤圆

发表于 2015-4-18 21:14:03 | 显示全部楼层
感谢楼主,收下学习学习

出0入0汤圆

发表于 2015-4-19 17:58:53 | 显示全部楼层
看的有点晕,有空再回来仔细研究。。

出0入4汤圆

发表于 2015-4-20 10:35:00 | 显示全部楼层
超详细的可移植FFT,多谢楼主!

出0入4汤圆

发表于 2015-4-20 10:35:49 | 显示全部楼层
超详细的可移植FFT,多谢楼主!

出0入0汤圆

发表于 2015-4-20 12:26:07 | 显示全部楼层

赞一个。

出0入0汤圆

发表于 2015-4-20 12:56:29 | 显示全部楼层
对FFT还真不明白

出0入0汤圆

发表于 2015-4-20 13:15:41 | 显示全部楼层
MARK一下!

出0入0汤圆

发表于 2015-4-20 13:57:35 | 显示全部楼层
很好的经验, 谢谢分享!

出0入0汤圆

发表于 2015-4-20 15:21:57 | 显示全部楼层
mark,谢谢分享

出0入0汤圆

发表于 2015-4-20 15:22:33 | 显示全部楼层
mark.谢谢分享

出0入0汤圆

发表于 2015-5-19 14:37:16 | 显示全部楼层
一段很好的资料,谢谢分享。

出0入0汤圆

发表于 2015-5-19 14:45:13 | 显示全部楼层
很快应该就要用到了

出0入0汤圆

发表于 2015-5-19 15:18:47 | 显示全部楼层
谢谢,以前都是拿AD算出来的,很费劲

出0入0汤圆

发表于 2015-5-19 15:28:38 | 显示全部楼层

赞一个。

出0入0汤圆

发表于 2015-5-19 21:19:10 | 显示全部楼层
以前买真有效值交流电压电流,以后可以试着玩下,自己弄

出0入0汤圆

发表于 2015-9-22 16:18:06 | 显示全部楼层
你这个成功了吗? 我在STM8上做64点FFT,fs=10KHZ,出来的结果不对,我加1KHZ出来的是第2个点的模最大. 应该是第7个点才对啊,adc的结果导入到excel中做FFT,求模也是第7个点的模最大.

出0入0汤圆

发表于 2015-9-23 12:02:52 | 显示全部楼层
顶一个,谢谢分享

出0入0汤圆

发表于 2015-9-23 22:17:55 | 显示全部楼层
MARK,学习一下,谢谢分享

出0入0汤圆

发表于 2015-9-23 22:33:02 | 显示全部楼层
多谢分享了

出0入0汤圆

发表于 2015-9-30 23:01:00 来自手机 | 显示全部楼层
mk    有心学习

出0入0汤圆

发表于 2015-10-5 00:23:56 | 显示全部楼层
非常感谢,

出0入0汤圆

发表于 2015-10-6 23:15:22 | 显示全部楼层
非常感谢,学习下!

出0入0汤圆

发表于 2015-10-7 00:56:45 | 显示全部楼层
这个好,很受用啊!!

出0入0汤圆

发表于 2015-10-7 12:39:06 | 显示全部楼层
上学听老师讲过傅立叶变换,也看过FFT,但是一直没有搞明白!也许是没有机会实际用过吧!

出0入0汤圆

发表于 2015-10-29 18:27:29 | 显示全部楼层
高手在民间....

出0入0汤圆

发表于 2015-10-30 08:35:49 | 显示全部楼层
收藏起来!!好有用!!!

出0入0汤圆

发表于 2015-10-30 08:45:31 | 显示全部楼层
收藏,学习一下

出0入0汤圆

发表于 2015-10-30 08:53:18 | 显示全部楼层
学习,谢谢分享
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 21:54

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表