我在24位长的位域(4字节消息的3个字节)中从ublox GPS模块接收数据,我需要将这些24位数据字段转换为带符号的十进制值,但我找不到描述在规范中如何做到这一点。此外,我知道模块附带的另一个程序的某些值。
对于正值,它似乎只是简单地将24位二进制数转换为dec,就是这样,例如0x000C19 = 3097
和0x000BD0 = 3024
,但对于负数,我遇到了麻烦。 2的补充似乎不起作用。以下是一些已知值:0xFFFFC8 = -57
,0xFCB9FE = -214528
,0xFF2C3B = -54215
和0xFFFA48 = -1462
。使用2的补码,转换每次都会关闭几个数字(分别为-56,-214530,-54213,-1464)。 (十六进制数用于避免每次都写24位数。)
提前感谢您的帮助!
答案 0 :(得分:1)
首先要做的事情是"已知"你所拥有的价值观并不是你认为的那样:
#include <stdio.h>
static void p24(int x)
{
printf("%8d = 0x%06X\n", x, (0x00ffffff & (unsigned)x));
}
int main(int argc, char *argv[])
{
p24(-57);
p24(-214528);
p24(-54215);
p24(-1462);
return 0;
}
在2s补充机器上进行编译和运行
-57 = 0xFFFFC7
-214528 = 0xFCBA00
-54215 = 0xFF2C39
-1462 = 0xFFFA4A
当转换为2s补码时,你当然要填充你正在使用的目标数据类型的全长,以便正确地继承符号。然后将签名数据类型向下划分为设计的位数。
例如:
#include <stdio.h>
#include <stdint.h>
/* 24 bits big endian */
static char const m57[] = {0xFF, 0xFF, 0xC7};
static char const m214528[] = {0xFC, 0xBA, 0x00};
static char const m54215[] = {0xFF, 0x2C, 0x39};
static char const m1462[] = {0xFF, 0xFA, 0x4A};
static
int32_t i_from_24b(char const *b)
{
return (int32_t)(
(((uint32_t)b[0] << 24) & 0xFF000000)
| (((uint32_t)b[1] << 16) & 0x00FF0000)
| (((uint32_t)b[2] << 8) & 0x0000FF00)
) / 256;
}
int main(int argc, char *argv[])
{
printf("%d\n", i_from_24b(m57) );
printf("%d\n", i_from_24b(m214528) );
printf("%d\n", i_from_24b(m54215) );
printf("%d\n", i_from_24b(m1462) );
return 0;
}
将打印
-57
-214528
-54215
-1462
答案 1 :(得分:0)
OP的信息不一致,可能@John Bollinger评论适用:&#34; ...执行转换的程序正在失去精确度......&#34;
OP需要审核并发布更多信息/代码。
OP's OP's 2's comp. Diff
Hex Dec
0xFFFFC8 -57 -56 -1
0xFCB9FE -214528 -214530 2
0xFF2C3B -54215 -54213 -2
0xFFFA48 -1462 -1464 2
由于此评论的复杂性,张贴为答案
答案 2 :(得分:0)
感谢大家尝试提供帮助,但我才意识到我已经迟钝了,甚至更加迟钝了!我得到了#34;已知值的程序&#34; from表示测量数据的缩放值,似乎+ -1 + -2偏差在转换后的0.001精度显示值的范围内,所以它确实使用2s补码。
抱歉,大家都失去了时间! (这太棒了)