已关闭,此问题需要details or clarity。目前不接受答复。
**想改善这个问题吗?**通过editing this post添加详细信息并澄清问题。
2天前关闭。
Improve this question
我有两个独立的字节的数据。在功能上,此数据组合以创建11位无符号数。我需要将其扩展到14位,然后再次将其拆分为两个字节并传输。我用这个帖子作为参考:Converting 8 bits to a scaled 12 bits equivalent
这里有一个转折:
在两种情况下都不使用最高有效位-无论是在传入数据还是传出数据中。因此,位0-6有效,位7无效。如果N=有效值,而X=无效值,则传入的数据看起来如下所示:
MSB:XXXXNNNN LSB:公司简介
传出数据需要看起来像这样:
MSB:XNNNNNNN LSB:公司简介
这是我的想法。有没有人能提出更准确的建议,或者看到我正在做的事情的问题?注:是的,LSB在设计中首先被放入发送缓冲器。
uint16_t FullVal = 0;
uint8_t LSB_Temp = 0;
LSB_Temp = ( Msg_Buff[Buff_Tail_Indx].RX_Data[2] << 1 ) | ( Msg_Buff[Buff_Tail_Indx].RX_Data[2] >> 1 ); //Shift 7-bit LSB value left then fill lsb
FullVal = ( Msg_Buff[Buff_Tail_Indx].RX_Data[1] << 8 ) | LSB_Temp; //Or together bytes
FullVal = (( FullVal << 3 ) | ( FullVal >> 3 )); //Scale 11-bit to 14-bit (missing bit is LSB bit 7)
TX_Data[1] = ( FullVal & 0x007F ); //Grab LSB, shift right to scale to 7 bits
TX_Data[2] = ( FullVal >> 8 ) & 0x00FF; //Grab MSB
3条答案
按热度按时间js81xvg61#
假设我们将包括第7位伪字节的数字称为“原始”,将去除该位的数学数字称为“值”。
就像这样:
输出:
jbose2ul2#
另一种方法,在我看来,这是一个明显更可读的代码,是让编译器做所有的艰苦工作,通过使用C语言的位字段功能。
使用位字段和联合定义数据的结构:
然后用这个来做你的计算:
输出:
Godbolt
注意:正如注解中正确指出的那样,C标准不保证位字段从LSB开始排序。所以这段代码不是严格可移植的。但事实上,这是我遇到的大多数编译器的情况。另外,如果使用C++,则可以添加验证顺序的static_assert。
gywdnpxw3#
**编辑:**虽然最初的答案通过构建组合值的所有方式,但实际上可以通过直接创建值来更有效地完成,跳过此组合值!
首先,按如下方式进行缩放:
在特定情况下:
它解决了
由于只涉及一个移位,您可以将其独立地应用于两个字节,然后您只需得到:
这只是移出最高有效位。这些,虽然需要在高字节集成!
已经这样了...
留下的常规部分用于创建组合值以供参考:
您的解释并不完全清楚相关位现在实际驻留在哪里,除了所有这些位至少占用各自字节中的最低有效位。自从你编辑了问题:将
lowBits
替换为7,将highBits
替换为4 -或更好:将它们定义为 * 常量 *。如果你想从一个字节中提取最低有效位,你可以通过简单地屏蔽掉高位来实现;为此,您需要一个掩码,其相关有效位为1,其他有效位为0;对于一般的
char
,您可以通过以下方式执行此操作:或者可选地
其中,在两种情况下,
n
是相关最低有效位的数量。剩下的就是:如果您想删除
m
最低有效位,然后使用下一个n
最低有效位,请执行以下操作戴着和以前一样的面具
现在假设您已经对消息中的两个字节执行了此操作。您现在希望将两者结合起来。为此,您需要将提取的位转换为16位值。因此,您需要适当地转换值(或从一开始就存储在16位变量中)。假设
k
位位于较低字节,则只需通过以下方式合并两个值:现在你有了最终的价值。然后,缩放就像往常一样发生:
但是,您需要确保没有溢出发生;通过将11位值缩放到14位值,您可能最终得到具有25个有效位的最大值;所以我们可以安全地使用32位来计算中间值:
好吧,在这个具体的例子中,我们还可以优化一点;当然,给定情况下的商简单地是
1<<3
(2^14 / 2^11 = 2^3),乘以1<<n
与直接移位n
相同,所以在具体情况下,你可以简单地有:现在所有组合:
请注意,无论输入数据是有符号的还是无符号的,都可以正确缩放-只要不关心有符号输入的缩放值中的两个最高有效位。你会 * 有符号的值,如果你例如。想把它们记录下来那么你需要符号扩展简单有效:
不幸的是,如果有符号值的右移是算术移位还是逻辑移位,则是实现定义的;如果您希望完全可移植,则可能需要考虑以下两种情况:
请注意,这是假设2的补码!其他格式不包括在内。
构建输出字节也很简单,我们可以从 unsigned scaled值开始:
这是有效的变体,不关心低字节内的最高有效位;如果这些 * 需要 * 设置为0,则需要屏蔽多余的位:
你不需要屏蔽高字节的位,这些都是0。