本帖最后由 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;
}
后续还有SIN,COS,TAN,ASIN,ACOS等衍生算法的。只用加减与移位就能完成的
个人觉得改成+-Pi 范围的Q15输出,而不是固定1600倍会更通用一点
一周热门 更多>