数字电源通信的Linear11和Linear16数据格式学习附代码

基本的东西我就不说了看链接文章

#数字电源的通信协议

Linear11数据格式 这种数据格式具有11位尾数和5位指数(请参见图2)。尾数和指数都是二进制补码整数,这表示它们可以是正数或者负数。
Linear11数据格式
数字电源通信的Linear11和Linear16数据格式学习附代码_第1张图片

使用公式(1)将实际值转换为Linear11格式:
XREAL WORLD=Y∙2N N可以为正或负, 2N定义了Y尾数LSB的大小。使用Linear11格式可以表示的最小数字是±2-16 x 1 = ±15.3e-6,最大数字为±33.5e6。 由于Signed(有符号)11位整数为-1,024至+1,023,尾数的大小应介于512和1,023之间。由此可以得出一种将实际值编码为PMBus Linear11格式值的方法。即N从-16开始递增,并保持尾数大小在所需范围之内。

文章的补充说明主要是关于负值计算

正值其实挺好理解的,就是负数值有点绕,上面文章写的不太清楚实际负数的值应该是在-512和-1023间正在512和1023间。博主的意思应该是11位中的低10位在512和1,023之间,不过那样写我一下没有看明白。

我搞个例子实现一下:
比如-45的计算步骤为:
-45 先乘16(2的4次方)变为-720在-512和-1023间。然后11位的-720对应的补码 0X800-720=0x530 。那么对应高5位为 0x20-4(4次方)=0x1c。将他们拼在一起就是0XE530。

//typedef __attribute__((packed))struct
typedef  struct
{
	int16_t base : 11;
	int16_t mantissa : 5;
} linear11_t ;	

typedef union
{
	linear11_t linear;
	uint16_t raw;
} linear11_val_t;

inline double linear11_to_double(linear11_val_t t)
{
	uint16_t X;
	int16_t N;
#if 1
	double data,data2;
	X=t.linear.base;
	N=t.linear.mantissa;
	data=X;
	data2= pow(2,N);
	data=data*data2;
	return data;
#else
	return t.linear.base * (double)(1 << t.linear.mantissa);
#endif
}

inline double linear11_to_double11(linear11_val_t t)
{
	int16_t X;
	int16_t N;
#if 1
	double data,data2;
	X=t.linear.base;
	N=t.linear.mantissa;
  if(N&(1<<5))
	data=X;
	else
	data=-X;
	
	data2= pow(2,N);

	data=data*data2;
	return data;
#else
	return t.linear.base * (double)(1 << t.linear.mantissa);
#endif
}

double L11_to_double(uint8_t *data)
{
	linear11_val_t fixed_temp;
	uint16_t r;
	double temp ;
	r=data[1];
	r=r<<8;
	r|=data[0];
	fixed_temp.raw=r;
	temp = linear11_to_double(fixed_temp);
	return temp;
}

double L11_to_double11(uint8_t *data)
{
	linear11_val_t fixed_temp;
	uint16_t r;
	double temp ;
	r=data[1];
	r=r<<8;
	r|=data[0];
	fixed_temp.raw=r;
	temp = linear11_to_double11(fixed_temp);
	return temp;
}

inline double linear16_to_double(linear11_val_t t)
{
	uint16_t X;
	int16_t N;
#if 1
	double data,data2;
	X=t.linear.base;
	N=t.linear.mantissa;
	data=X;
	data2= pow(2,N);
	data=data*data2;
	return data;
#else
	return t.linear.base * (double)(1 << t.linear.mantissa);
#endif
}

double L16_to_double(uint8_t *data)
{
	uint16_t r;
	double temp ;
	r=data[1];
	r=r<<8;
	r|=data[0];
	temp=(int16_t)r;	
	temp *=pow(2,-12) ;
	return temp;
}

你可能感兴趣的:(嵌入式硬件)