我需要通过串行线(RS-232)接收来自Arduino的十六进制编码单精度大端浮点值。如何将它们转换为Python双精度浮点数的浮点数?单精度大端浮点值到Python浮点数(双精度,大端)
Arduino发送类似“8192323E”的东西,在Python中我想要0.174387。我发现“Convert hex to float”,但它似乎都不适用于单精度浮标。
从链接的页面,这看起来很有希望:
from ctypes import *
def convert(s):
i = int(s, 16) # convert from hex to a Python int
cp = pointer(c_int(i)) # make this into a c integer
fp = cast(cp, POINTER(c_float)) # cast the int pointer to a float pointer
return fp.contents.value # dereference the pointer, get the float
但它仍然无法与我的单精度浮点数工作。
在Java(Processing)我已经能够做到这一点:
float decodeFloat(String inString) {
byte [] inData = new byte[4];
inString = inString.substring(2, 10); // discard the leading "f:"
inData[0] = (byte) unhex(inString.substring(0, 2));
inData[1] = (byte) unhex(inString.substring(2, 4));
inData[2] = (byte) unhex(inString.substring(4, 6));
inData[3] = (byte) unhex(inString.substring(6, 8));
int intbits = (inData[3] << 24) | ((inData[2] & 0xff) << 16) | ((inData[1] & 0xff) << 8) | (inData[0] & 0xff);
//unhex(inString.substring(0, 8));
return Float.intBitsToFloat(intbits);
}
供您参考,这是Arduino的运行实现十六进制编码的C代码。
void serialFloatPrint(float f) {
byte * b = (byte *) &f;
Serial.print("f:");
for(int i=0; i<4; i++) {
byte b1 = (b[i] >> 4) & 0x0f;
byte b2 = (b[i] & 0x0f);
char c1 = (b1 < 10) ? ('0' + b1) : 'A' + b1 - 10;
char c2 = (b2 < 10) ? ('0' + b2) : 'A' + b2 - 10;
Serial.print(c1);
Serial.print(c2);
}
}
你可以举一些如何使用ctypes代码解码浮点数的例子吗?我的第一个怀疑是字节顺序。您可能需要交换字节才能正确解码。 – 2010-11-30 15:13:21
在其流线: F:FFFF7F7F F:FFFF7FFF F:8192323E F:00000000 虽然ctypes的代码读取: 'FFFF7F7F' 楠 'FFFF7FFF' 楠 '8192323E' -5.37040237597e-38 '00000000' 0。0 – 2010-11-30 15:20:41
由于Arduino处理器是小端(AFAICT)处理器,运行在其上的C代码在执行十六进制编码时首先处理低位字节 - 因此,当所有四个字节按照生成的顺序连接在一起时,它们将回退到正常方式写入和解释多字节十六进制(和多位十进制)数字。这与Java解码器代码“起作用”(以及我的答案)一致。 – martineau 2010-12-01 11:53:21