Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/drupal/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Embedded 数据转换:将数组中的4字节数据分配到1字节数组中_Embedded_Microcontroller_Generic Programming - Fatal编程技术网

Embedded 数据转换:将数组中的4字节数据分配到1字节数组中

Embedded 数据转换:将数组中的4字节数据分配到1字节数组中,embedded,microcontroller,generic-programming,Embedded,Microcontroller,Generic Programming,首先,让我解释一下环境。我正在使用C作为嵌入式32位微控制器。通过各种工具进行单元测试,但结果是相同的。printf仅用于使用MinGW的测试 我试图将数据从float32数组(4字节数组)(IEEE754)复制到字节数组中 我在这里仅使用十六进制数据,十六进制值的位置必须准确,即: If CalibData[0] = 01 02 03 04 那么数据应该如下所示: Data[0] = 01 Data[1] = 02 Data[2] = 03 Data[3] = 04

首先,让我解释一下环境。我正在使用C作为嵌入式32位微控制器。通过各种工具进行单元测试,但结果是相同的。printf仅用于使用MinGW的测试

我试图将数据从float32数组(4字节数组)(IEEE754)复制到字节数组中

我在这里仅使用十六进制数据,十六进制值的位置必须准确,即:

If CalibData[0] = 01 02 03 04
那么数据应该如下所示:

   Data[0] = 01
   Data[1] = 02
   Data[2] = 03
   Data[3] = 04
我能想到的可能性类似于下面提到的代码块:

/*CalibData is a Global variable and change by other components, I am only reading it here*/
float32 CalibData [1920];

/*Data is an argument for my function and shall return it with values read from CalibData*/
int Data[7680];

/* Approach 1: */

uint16_t dataElementCounter = 0;
for (uint16_t i = 0; i < 1920; i++)
{
Data[dataElementCounter] = (uint8) ((uint32) calib_Data[i] >> 24);
dataElementCounter++;
Data[dataElementCounter] = (uint8) ((uint32) calib_Data[i] >> 16);
dataElementCounter++;
Data[dataElementCounter] = (uint8) ((uint32) calib_Data[i] >> 8);
dataElementCounter++;
Data[dataElementCounter] = (uint8) ((uint32)calib_Data[i]);
dataElementCounter++;
}

/* Approach 2: */
for (uint16_t i = 0; i < 1920; i++)
{
memcpy((uint8*) Data[0], &calib_Data[i],sizeof(float));
}
根据IEEE754,十六进制格式应为0x3F 0x80 0x00 0x00,但在单元测试或printf中,它将按如下方式执行:

   Data[0] = 01
   Data[1] = 02
   Data[2] = 03
   Data[3] = 04
CalibData>>24是分数1.0/16777216。转换为uint32时,它将截断为0。 CalibData>>16是分数1.0/65536。同样地 CalibData>>8是分数1.0/256。同样地 CalibData为1.0。这将成为1作为uint32

因此,数据将显示为:

Data[0] = 0
Data[1] = 0
Data[2] = 0
Data[3] = 1
若我使用的是方法2,那个么代码就是在数据中显示垃圾值

请告诉我一个更好的方法或改进上述方法之一


将错误视为演员
(uint32)
,因为它正在将
浮动
转换为
uint32
,而这不是您想要的

你最好的选择是以下摘录:

union {
    float f;
    uint8 b[4];
} u;

u.f = calib_Data[i];
Data[dataElementCounter] = u.b[0];
dataElementCounter++;
Data[dataElementCounter] = u.b[1];
dataElementCounter++;
Data[dataElementCounter] = u.b[2];
dataElementCounter++;
Data[dataElementCounter] = u.b[3];
dataElementCounter++;
注意,这不符合C标准。但它可能在您的实际系统上工作

编辑1

仍然不符合要求,但不使用
联合
,您可以使用铸造指针来模拟:

const uint8* b = (const uint8*)(calib_Data + i); // equally, but simpler to read than &calib_Data[i]
Data[dataElementCounter] = b[0];
dataElementCounter++;
Data[dataElementCounter] = b[1];
dataElementCounter++;
Data[dataElementCounter] = b[2];
dataElementCounter++;
Data[dataElementCounter] = b[3];
dataElementCounter++;
这与codetest的答案类似,后者甚至建议使用
memcpy()

最后一个选项有两个主要优点:

  • 用尽可能少的行就可以理解了
  • 它对
    校准数据的数据类型大小的更改是安全的
  • 编辑2

    要求:您必须交换字节

    如果您的目标系统是固定的,并且如果您完全确定自己在做什么,那么首先要做的就是将其记录在注释中。此外,您可能希望检查编译器:

     #if !defined(MY_COMPILER_ID)
     #error Compiler not supported
     #endif
    
    要以相反的顺序存储浮点值,可以使用“编辑1”的第一个备选方案和反向索引:

    const uint8* b = (const uint8*)(calib_Data + i); // equally, but simpler to read than &calib_Data[i]
    Data[dataElementCounter] = b[3];
    dataElementCounter++;
    Data[dataElementCounter] = b[2];
    dataElementCounter++;
    Data[dataElementCounter] = b[1];
    dataElementCounter++;
    Data[dataElementCounter] = b[0];
    dataElementCounter++;
    
    为了使其在将来不会因
    calib_Data
    的数据类型的大小变化而变得安全,您需要一个循环:

    const uint8* b = (const uint8*)(calib_Data + i); // equally, but simpler to read than &calib_Data[i]
    int b_i;
    for (b_i = sizeof calib_Data[i] - 1; b_i >= 0; --b_i) {
        Data[dataElementCounter] = b[b_i];
        dataElementCounter++;
    }
    

    感谢您的回答,您的分析是正确的,但不幸的是,由于一些一致性限制,我无法在代码中使用联合谢谢您的详细回答,我发现您的第二种方法非常有用,现在我可以在调试器中看到正确的数据,但它被翻转了。例如,我期望数据[0]=3F数据[1]=80数据[2]=00数据[3]=00,但我得到的结果如下:数据[0]=00数据[1]=00数据[2]=80数据[3]=3F你能建议改变这个顺序吗?不幸的是,第一种方法不适用于我,返回0x00 0x00 0x00 0x01作为我自己的代码,但memcpy方法似乎工作正常,但只有reuslts被翻转。我想不出如何用memcpy翻转浮动顺序。不过,感谢您对安全性的非常好的解释和附加信息。我一定会这样做。如果
    memcpy()
    似乎有效,只要翻转一下,您的
    数据的数据类型就不是
    int
    ,而是
    uint8\u t
    或其他大小为1的数据类型。-正如您所发现的,
    memcpy()
    无法翻转。你必须自己做。你是对的,我自己在memcpy之后翻转字节,它就像魅力一样工作。非常感谢你的指导。现在问题解决了。“嵌入式32位微控制器?”你知道不止一个,对吗?
    const uint8* b = (const uint8*)(calib_Data + i); // equally, but simpler to read than &calib_Data[i]
    int b_i;
    for (b_i = sizeof calib_Data[i] - 1; b_i >= 0; --b_i) {
        Data[dataElementCounter] = b[b_i];
        dataElementCounter++;
    }