本帖最后由 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;
}
开头就有说明,解析出的角度放大了1600倍,右移4位就是除了16,就成了放大100倍,当然就是输出精度(更准确的说法是解析率)为0.01度了
你这个是不错的近似算法;
如果是STM32或上位机都可以;
但相对于8位单片机来说,有以下不利之处:
1. 需要使用浮点运算,速度与空间上都不利;
2. 精度不够,在360度范围内,最大误差有近0.3度,而我的是<0.01度
当然,算法并没有对错,只是应用场合不同。我的是用于STM8S003上的,
空间不够,速度还有要求,所以不得不做了这个整数算法
一周热门 更多>