程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 定浮點FFT在DM642中的運行報告

定浮點FFT在DM642中的運行報告

編輯:關於C語言

FFTDM642中的運行報告   1 FFT編程思想程序清單見附錄) 本算法采用了運算量較大但效果較好的動態溢出檢查。也就是說在計算每一級之前,對所有值進行遍歷,如果發現有超過溢出允許輸入值的變量,則對整個數組進行右移縮小處理。這樣就保證了數值較小的輸入不會被過度縮放,而數值很大的數據也能夠通過FFT運算。由於對所有的數組值進行縮放,因此不會造成失真,但是幅度大小會有變化。因此可以理解為定點算法只求解相對值。下面詳細介紹縮放方法: 一個乘加運算可以理解為: X1+X2*WN 我們需要找出在什麼情況下輸出會最大,並在設定輸出在此數據類型允許值下時,輸入最大取多少。由於X1,X2,WN都為復數,且abs(X2)=abs(X2*WN),因此最壞的情況是,在模一定的情況下,原來X2的實部和虛部的數值經過旋轉因子,被全部轉移到了實部,而虛部為零。或者反之。而由於當X2的實部和虛部相等時,它的模值最大,假設全部轉移到實部,在加上X1的實部的值就構成了最大的輸出。我們另這個最大的輸出等於類型最大允許值8bit時為0x7f,16bit時為0x7fff),由於我們需要對所有輸入做統一的限定值以便程序判斷,所以只能有X1.real=X2.real<max,此值得到的最壞情況下輸出為 Sqrt(X2.real^2+X2.imag^2)+X1.real= Sqrt(2*X2.real^2)+X1.real=(sqrt(2)+1)X1.real 我們將此輸出值限定在類型數據允許的最大整數上,則有 (sqrt(2)+1)X1.real<MAX 其中(sqrt(2)+1)為常數=2.4142得到X1.real最大不能超過MAX/2.4142,虛部一樣。繼續觀察運算我們發現,2.4142為大於2小於4的數字,因此,最多可能在同一級上溢出兩個bit,我們動態的調整縮放的量級則會改善上述情況。也就是在溢出兩位時除以4,溢出一位時除以2,經過計算機模擬,發現此時只要滿足單極不溢出的條件如8bit時為52)則總體就不會溢出,但是,付出的代價是兩個bit的精度被處理掉了。因此整體的精度為7bit-2bit8bit-符號位)=5bit,當然誤差可能由於多次這樣的操作而累積。程序中,實現時在每次進入新的一級運算之前,將所有值遍歷,如果超出2倍的ovs值則除以4,超出一倍除以2,否則不處理。這樣,乘加運算在數據類型內部不會造成溢出了。   2 定浮點FFTDM642中的運行結果運行時間和精度比較) 定浮點FFT程序在CCS中的運行結果如下圖1,2。 經過在MATLAB中驗證數據浮點程序運行結果正確。對於定點程序,我們看到標識位三個ov=1;故輸入的八個數據總共被縮小2^3=8倍。所以,把所有的定點數據換算成浮點數據然後再乘以8即得到實際數據,經驗算結果正確。 本例在CCS中設定的周期時間是40ns,觀察兩個程序的運行周期,浮點程序的運行周期是99510個,所以其運行時間是99510*40ns=3.9804ms。定點程序的運行周期是56143個,所以其運行時間是56143*40ns=2.24572ms。二者相差的時間數量級是1.7個ms,相差的相對百分比是3.9804-2.24572)/9.9804=43.58%。 對於定點運算的精度,計算公式如下:n=m/32768*8.最後得到的16個數據為: 3.598877  0  -0.400391  0.965576  -0.399902  0.399902  -0.400391  0.165771 0.399658  0  -0.399902  0.165771  -0.399902  -0.399902  -0.399902  0.965576 與浮點所得結果差值的絕對值為: 0.001123  0  0.000391  0.000104  0.000098  0.000098  0.000391  0.000089 0.000342  0  0.000098  0.000089  0.000098  0.000098  0.000098  0.000104 其平均值為:0.000226 其差值的百分比為0.003612/9.06272=0.03986%.   圖1 浮點程序運行結果 圖2 定點程序運行結果           附:FFT定浮點程序清單 浮點程序: #include<stdio.h> struct complex {        double real;        double imag; }; struct complex x[8]={{0.1,0.0},{0.2,0.0},{0.3,0.0},{0.4,0.0},{0.5,0.0},{0.6,0.0},{0.7,0.0},{0.8,0.0}}; struct complex cheng,y[8]; double costable[7]={1.0000,1.0000,0.0000,1.0000,0.7071,0.0000,-0.7071},sintable[7]={0.0000,0.0000,1.0000,0.0000,0.7071,1.000,0.7071}; int reverse(int i) {          int a[3],b,j=0;         for(b=0;b<3;b++)        {           a[b]=(1&i)<<(2-b);           j=j+a[b];           i/=2;        }        return j; } void paixu() {        int i,j;        for(i=0;i<8;i++)        {               j=reverse(i);               y[j].real=x[i].real;               y[j].imag=x[i].imag;        }     } void main() {               int m=4,n=1,i,j,k,num1,num2;        paixu();        for(i=0;i<3;i++)        {               for(j=0;j<m;j++)               {                      for(k=0;k<n;k++)                      {                             num1=2*n*j+k;                             num2=num1+n;                             cheng.real=y[num2].real*costable[(1<<i)+k-1]+y[num2].imag*sintable[(1<<i)+k-1];                         cheng.imag=y[num2].imag*costable[(1<<i)+k-1]-y[num2].real*sintable[(1<<i)+k-1];                                               y[num2].real=y[num1].real-cheng.real;                             y[num2].imag=y[num1].imag-cheng.imag;                             y[num1].real=y[num1].real+cheng.real;                             y[num1].imag=y[num1].imag+cheng.imag;                      }               }               m/=2;               n*=2;        }        for(i=0;i<8;i++)        {               printf("%f\n%f\n",y[i].real,y[i].imag);        }   }       定點程序: #include<stdio.h> struct complex {        int real;        int imag; }; struct complex x[8]={{3276,0},{6553,0},{9830,0},{13107,0},{16384,0},{19660,0},{22937,0},{26214,0}}; struct complex cheng,y[8]; int costable[7]={32767,32767,0,32767,23170,0,-23170},sintable[7]={0,0,32767,0,23170,32767,23170}; int reverse(int i) {          int a[3],b,j=0;         for(b=0;b<3;b++)        {           a[b]=(1&i)<<(2-b);           j=j+a[b];           i/=2;        }        return j; } void paixu() {        int i,j;        for(i=0;i<8;i++)        {               j=reverse(i);               y[j].real=x[i].real;               y[j].imag=x[i].imag;        }     } void main() {        int p,i,j,k,num1,num2,m=4,n=1,ov=0,ovd=0;        paixu();          for(i=0;i<3;i++)        {                                                         for(p=0;p<8;p++)               if (y[p].real>27146 || y[p].imag>27146 || y[p].real<-27146 || y[p].imag<-27146)                           //超出兩倍允許值,所有值右移2個bit               {                      ovd=1;                      break;               }            else if (y[p].real>13573 || y[p].imag>13573 || y[p].real<-13573 || y[p].imag<-13573)                     //超出允許值,所有值右移1個bit               {                      ov=1;               }            if (ovd==1)               for(p=0;p<8;p++)               {                      y[p].real=y[p].real>>2;                      y[p].imag=y[p].imag>>2;               }               else if(ov==1)            for(p=0;p<8;p++)               {                      y[p].real=y[p].real>>1;                      y[p].imag=y[p].imag>>1;               }               printf("%d\n%d\n",ovd,ov);               for(j=0;j<m;j++)               {                      for(k=0;k<n;k++)                      {                                                         num1=2*n*j+k;                             num2=num1+n;                             cheng.real=((y[num2].real*costable[(1<<i)+k-1])>>15)+((y[num2].imag*sintable[(1<<i)+k-1])>>15);                         cheng.imag=((y[num2].imag*costable[(1<<i)+k-1])>>15)-((y[num2].real*sintable[(1<<i)+k-1])>>15);                 //cheng.real=x[num2].real*cos(pi*k*m/4)+x[num2].imag*sin(pi*k*m/4);                             //cheng.imag=x[num2].imag*cos(pi*k*m/4)-x[num2].real*sin(pi*k*m/4);                                                        y[num2].real=y[num1].real-cheng.real;                             y[num2].imag=y[num1].imag-cheng.imag;                             y[num1].real=y[num1].real+cheng.real;                             y[num1].imag=y[num1].imag+cheng.imag;                      }               }               m>>=1;               n<<=1;        }        for(i=0;i<8;i++)        {               printf("%d\n%d\n",y[i].real,y[i].imag);        }   }  

本文出自 “嵌入式學習” 博客,請務必保留此出處http://mousimin.blog.51cto.com/1624003/319026

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved