关于DSP的一些反正切查表算法的编写
一直在拿TMS20F28335做电机控制,也从早前的简单寄存器IO口配置时代过渡到了真正的算法时代,很不适应,起初去查各种书籍,网上搜索各种网站,发现书本上讲的很多都是快速傅里叶啊啥的,找不到很原始的像啥低通滤波器,正弦,正切这些函数的编写。
起初写程序发现,C2000的库里支持啥正弦函数,浮点预算,反正弦函数,开根运算等算法,好兴奋。用了才知道,太慢了,根本没法用在工程上。
关于三角函数的编写,其实都是利用查表发,查表法大家应该都懂。这个就不再赘述,怎样去查一个正弦表呢?这里做一个基本的介绍。
首先,你可以自己写一个查表数组,也可以在程序初始化生成一个。
Eg:
void SinCOS_TAB(void)
{
unsigned char i;
float Theta;
for(i=0;i { Theta = i * Step_Angle; // Step_Angle=1.74532925E-02 Sin_tab[i] =sin(Theta); // 生成正弦表数组,利用了库里现成的SIN函数 Cos_tab[i] =cos(Theta); // 生成余弦表数组 } } 为啥我的数组里面只有180个元素呢?一:我的精度要求不高,我是一度一个步进角的,如果你要更高的精度,你可以选择容量更大的数组。二:我不想因为庞大的浮点数组占据太大的存储空间,所以我利用了奇函数,偶函数的原理 再次,就进入正题写查表程序,就我们初中数学所知,正弦函数是奇函数,余弦函数是偶函数,所以我只用了360角度中的一半。 下面为正弦查表程序: /*Refer to the truth that DSP use some SinCos operation will use six or more command * periods , So I look up the pre_generate SINCOS_TAB to speed up the Execution speed*/ float SinF(float single) { int i=(int)(single*180/pi); float value=0; if(i<0) value = -Sin_tab[i]; else value = Sin_tab[i]; return value; } 看起来应该很简单吧,余弦,正切,余切的编写和上面基本相似。 下面来探讨一下反正弦,反正切函数的编写 我在网上查了一下,运用函数库的反正弦,正切指令计算一个至少需要400以上各时钟周期,网上也有很多方法,看了有些能看懂,但大多看了头疼。自己呢,还是从正切函数的曲线出手,利用单调递增写了一个查表函数,已在MATLAB上实验过。 一次函数线性逼近正弦函数 这是我算法在MATLAB上面实验的程序: function single = tanflook( a ) %UNTITLED Summary of this function goes here % Detailed explanation goes here global theta; %global single; global Actan_tab; global x; global res; theta=-90:90; theta=theta*3.141596/360; Actan_tab=1000*tan(theta); pi z=input('the Z scale is :'); y=input('the Y scale is :'); a=(z+y>=0); a b=(z-y<=0); b if((a==b)) single = z/y; else single = y/z; end tab =fix(single*99-8)+90; tab comp=fix(single*1000); for i=tab:181 if(comp>=Actan_tab(i))&&(comp break; % else % i=i+1; end end i c = (i>90); c single= (i-90)/360*pi; x=2*b+a; % x=2; switch x case 0 single=-pi/2-single;%break; %case 0:single=single;break; case 1 ;%break; case 2 single=pi+single-2*pi*c;%break; case 3 single=pi/2-single;%break; end x disp('the single value is '); disp(180*single/3.141596); End 讲讲原理吧,感觉还是有点东西,还是从那个一次函数线性逼近正弦函数的地方说起,为什么要这样了,因为我们从图上可见发觉,每一个正弦值其实都在某段线性函数包围之间,我们已知了正切值,利用正切函数的线性递增原理,可以大致推断出他所处的大概位置,然后再查建立好的表,这里就不要再用处理器去生成了,查表时应尽量避免浮点数运算来节约时间,我们就可以精确的算法所对应的角度。试验了一下,最差的情况下差不多要消耗40个时钟周期。 关于上面几个CASE的推导,可以仿造SVPWM里面推导CASE的方法,感兴趣的可以推导一下,还是蛮有意思的,千万不要糊涂。 东西感觉不是很多,主要自己会的比较少,希望对大家有帮助,如果那个地方讲的不对,还请大神能及时指出,与我进行交流,我很喜欢和别人探讨