1

我正在调试一个问题,即缓冲区中的数据获取错误值。我将缓冲区(u8)类型从内核驱动程序发送到 HAL。在 HAL 中,有一个Uint16缓冲区正在接收来自该缓冲区的值。

//Code to copy BUFFLEN contents from u8 data[BUFFLEN] into uint16_tData ;

uint16_t uint16_tData[BUFFLEN / 2];
float floatdata[BUFFLEN / 2];

uint16_tData使用这种类型转换从缓冲区中获取浮点值:

floatdata[index] = (*((float *)((void *)&uint16_tData[index1];

现在我的问题是:如何解释floatdata数组中的数据?说我有数据floatdata[0] = 53640;

如何从这个半字节中解释浮点数据floatdata[0]

注意 u8 中的 4 个字节 --> 数组 uint16_tData 的 2 个元素 --> 数组 floatdata 的一个元素。

我想知道一个例子,说:

从驱动程序传输的值是:

u8 val1 = 206
u8 val2 = 208
u8 val3 = 120
u8 val4 = 68

在 HAL 中,转换将如何进行,我将在这里获得什么值?

uint16_tData[0] = ?
uint16_tData[1] = ?

以及如何将数据解释为浮点数floatdata

floatdata[0] = ?
4

4 回答 4

1

为什么要这样做?

我想你想要这个:

float *floatdata;

floatdata = (float *)uint16_tData;

// Now use floatdata[index] ...

一次铸造一件物品是愚蠢的。从 uint16_t 转换为 float 甚至更愚蠢,最好将其保留为 uint8_t (字节),这似乎是它的样子,或者至少使用 uint32_t 作为中间体。

有什么阻止你这样做的吗?你能想到如何重新设计你的代码,这样你就可以完全避免处理这些问题吗?

于 2013-10-29T07:25:18.067 回答
1

根据我对你的问题的理解,这就是你想要的

float f ;
uint8_t u8arr[4]={206,208,120,68};
uint16_t arr[2];
memcpy(&arr[0],u8arr,2);
memcpy(&arr[1],u8arr+2,2);
memcpy(&f,arr,4);
于 2013-10-29T07:38:37.210 回答
1

uint16是“由” 2 组成的u8,单精度float是 32 位(4 u8 或 2 uint16),但是它们如何“转换”取决于处理这些数据的代码,特别是“发送”的含义(来自内核驱动程序)以及“接收”的代码如何期望数据。我承认我对这个话题一无所知,我现在无法检查和研究它,但我怀疑你有字节序问题:你的数据完全有“意义”,而不是单个八位字节,但你把它们放在内存中错误的顺序。

基本上,你有一个包含你的八位字节的缓冲区,比如说

A   B   C   D
u8  u8  u8  u8      4 u8 arr element (arr[0], arr[1] ...)
\____/  \____/  
 uint16   uint16    2 uint16 arr element (arr[0] and arr[1]) 

按照内存地址递增的顺序。如果您希望将A B其读取为“正确”的 uint16 数字,则必须在内存中对其进行“排序”,以便与处理器的字节序相匹配:例如,如果您想要在A*8 + B小端 cpu 上的数字,则必须写两个u8 在内存中的顺序相反:

B A D C

我怀疑 HAL 使用 uint16 只是为了存储数据,而不是将它们解释为 16 位数字,所以这里的字节序不是问题。但是,一旦您想从内存中的 4 u8(或 2 uint16)中获得正确的“浮点数”:您必须将 u8 以正确的顺序放置。

如果您希望您的 u8 通过强制转换被解释为浮点数,您首先必须将它们以相反的顺序放入小端机器中,例如

  address of arr8[0] and arr16[0]
/
D   C   B   A
u8  u8  u8  u8      4 u8 arr element (arr8[0], arr8[1] ...)
\____/  \____/  
 uint16   uint16    2 uint16 arr element (arr16[0] and arr16[1]) 

然后,如果你在小端机器上“读取”这些八位字节作为浮点数,那么你就有了正确的“浮点数”。

所以,由你来正确排序你的 u8,知道它们将被解释为另一种类型,其“宽度”比一个八位字节更宽。可移植代码应使用正确的方法为具有不同字节序的处理器正确编译。

另请参阅此维基百科文章

于 2013-10-29T08:36:05.050 回答
0

我对 HAL/DX 不友好,所以这可能是一个愚蠢的说明
,但你确定你的浮点数是 16 位而不是 32 位吗?

好的,现在你的问题是什么:

  1. 你有 uint 缓冲区但里面存储浮点数?

    • 在这种情况下,只需这样做:

      float16 *p=(float16*)uint16_tData;
      
    • 并使用 p 而不是 uint16_tData
  2. 你有 uint 缓冲区,里面存储了 uint 值?

    • 这意味着您需要将 uint 转换为 float
    • 如果存在,则使用内部 = 运算符
    • 如果不写你自己的转换
    • 您可以忽略 uint 的符号
    • 将 exp 设置为 0 (2^0)
    • 将尾数设置为 uint 值
    • 截断不合适的位
    • 只需右移 / inc 指数,直到 uint 的 MSB 适合尾数
    • 将所有内容与位移/和/或它们的位置放在一起(请参阅上面的链接)
  3. 您有浮点值,需要将它们作为 uint 存储在 uint 中

    • 所以简单地向后做一点
    • 提取指数、尾数、忽略符号或使用 2'os 补码
    • 将尾数左移指数(如果为正),否则右移 -exponent
    • 就是这样。

PS。请注意,在某些平台/编译器/数据类型上,位移也可以插入来自进位或数字另一侧的位移。在这种情况下,结果带有位掩码。

聚苯乙烯。不要忘记应用指数偏差!

希望它有一点帮助

于 2013-10-29T07:37:13.790 回答