本帖最后由 s1j2h3 于 2017-3-14 21:02 编辑
加入这个论坛,大部时间都在潜水,今天刚完成一个纯整数乘加运算的快速反正切算法,用于加速度传感器解析倾角。
大家评价下,看能否再优化
解析出的为放大了1600倍的角度值,右移四位就是精度为0.01度的角度值,范围为0~360度
编译完成的整个代码不到500字节,大家可以用IAR FOR STM8验证一下。
const static INT16U __tanz[] =
{
32767 ,
16384 ,
8192 ,
4096 ,
2048 ,
1024 ,
512 ,
256 ,
128 ,
64 ,
32 ,
16 ,
8 ,
4 ,
2 ,
1 ,
};
const static INT32U __angle[] =
{
72000 ,
42504 ,
22458 ,
11400 ,
5722 ,
2864 ,
1432 ,
716 ,
358 ,
179 ,
90 ,
45 ,
22 ,
11 ,
6 ,
3 ,
};
static INT32U __atan_core(INT16U tan)
{
INT32S x,y;
INT32S xt,yt,t;
INT16U *ptan;
INT32U *pang;
INT32U m,ang;
x = 65535;
y = tan;
ptan = (INT16U *)&__tanz;
pang = (INT32U *)&__angle;
m = 0;
for(INT8U i=0; i<16; i++)
{
t = *ptan++;
ang = *pang++;
yt = y*t;
xt = x*t;
yt >>= 15;
xt >>= 15;
if(y>0)
{
x += yt;
y -= xt;
m += ang;
}
else
{
x -= yt;
y += xt;
m -= ang;
}
}
return m;
}
INT32U __FastIntAtan2__(INT16S x, INT16S y)
{
INT8U flag = 0;
INT32U angle;
if(x<0)
{
x = -x;
flag |= 0x01;
}
if(y<0)
{
y = -y;
flag |= 0x02;
}
if(y>x)
{
INT16S t;
t = y;
y = x;
x = t;
flag |= 0x04;
}
{
INT32U m = y;
m *= 65535;
m /= (INT16U)x;
angle = __atan_core(m);
}
if(flag & 0x04)
{
angle = 144000 - angle;
}
if(flag & 0x01)
{
angle = 288000 - angle;
}
if(flag & 0x02)
{
angle = 576000 - angle;
}
return angle;
}
其实思路是一样的。不过我上面的代码只是稍微变化了点,更适合于我的应用而已。
而且,整数应用是没法做出通用版的。
最终精度是以0.1度,0.01度,还是0.001度为好?
应用不同,需要也不同。
这个,好像不行
预算好的正切值也需支持到相应的精度,否则光比例缩放是没有用的。
精度的大小也同样对应于查找的次数。
按你的想法,最好的就是提供足够的精度与足够的查找次数,而对于0.1度精度就能满足要求的需要求来说,你提供了0.001度的精度,那就多浪费了约7次的查找过程。
如果你不在乎这7次处理时间,那差不多也不在乎存储空间,那直接调用浮点库函数就行了
一周热门 更多>