【问题标题】:TI CC2530 - Convert a float to uint8[] for sending and then convert back to float in receptionTI CC2530 - 将浮点数转换为 uint8[] 以进行发送,然后在接收中转换回浮点数
【发布时间】:2013-12-05 20:55:22
【问题描述】:

我需要在一些德州仪器 CC2530 节点之间发送一些浮点数。 这种架构只能发送一个uint8数组。
我已经尝试做的是将带有强制转换的浮点指针分配给 uint8 指针。 然后我发送这些字节,当接收到它们时,它们被复制到一个 uint8 数组中。 最后,我创建了另一个浮点指针,该指针设置了先前创建的数组的强制转换。
实际上,这个技巧适用于我的电脑(使用 unsigned char 而不是 uint8),但不适用于接收到的数字始终为 0 的节点。

这是传输事件中使用的代码部分(它在那里创建msa_Data1,即传输的数据包,其中要发送的数字是valMed(全局变量)):

void Data_create(){
    uint8 *sends;
    sends = (uint8 *) &valMed;
    uint8 rec_index;
    for(rec_index=0; rec_index < sizeof(float); ++rec_index){
        msa_Data1[rec_index]= sends[rec_index];
    }
}

在接待区我有:

uint8 receiveds[sizeof(float)];
uint8 rec_index;
    for(rec_index=0; rec_index < sizeof(float); ++rec_index){
        receiveds[rec_index]= pData->dataInd.msdu.p[rec_index];
    }
float *received= (float *)receiveds;

来自传输的数据被pData-&gt;dataInd.msdu.p[rec_index]接收

我在pc上试过的传输模拟是:

main(){
    float send= -3.14;
    unsigned char *sends;
    sends = (unsigned char *)&send;
    printf("1:%d, 2:%d, 3:%d, 4:%d \nfloat sent:%f \n", sends[0], sends[1], sends[2], sends[3], send);
    unsigned char receiveds[sizeof(float)];
    int rec_index;
    for(rec_index=0; rec_index < sizeof(float); ++rec_index){
        receiveds[rec_index]= sends[rec_index];
    }
    float *received= (float *)receiveds;
    printf("float received:%f\n", *received);
} 

输出:

alex@aspire7738G ~/test $ ./test 
1:195, 2:245, 3:72, 4:192 
float sent:-3.140000 
float received:-3.140000

在这种情况下,我可以看到测试在 pc 上运行良好,但在节点上却没有。 怎么了?

提前感谢您的帮助!

亚历克斯

【问题讨论】:

  • 接收端能否“异相”接收来自第一个数据包的结束字节和下一个数据包的开始字节?如果可能,您的数据包需要增加大小以包含一些内容,以确保在通信期间正确对齐。
  • 数据包大小应该足以满足该范围,我有 20 个字节的数据包,而浮点数只有 4 个字节。此外,创建的数据包将数据设置在要发送的阵列的正确位置,这甚至消除了反向重新排序问题(串行通信的经典问题)。谢谢!

标签: c msp430 texas-instruments


【解决方案1】:

接收部分的代码有问题。您将字节复制到receiveds,然后使用指针转换将其视为float。但是,许多 C 实现对字符/字节类型使用一字节对齐(@9​​87654323@ 可能是这样),对float 类型使用四字节对齐。将uint8 指针转换为float 指针可能会导致指针对齐不正确。

相反,您可以这样做:

float received;
… // Code that prepares receiveds goes here.
memcpy(&received, receiveds, sizeof received);

此外,如果pData-&gt;dataInd.msdu.p 是字节数组或指向字节的指针(charunsigned char,或者,很可能,uint8uint8 是 C 实现中的字符类型),那么您可以省略使用receiveds作为中间缓冲区,直接复制:

float received;
// Omit the code that copied into receiveds.
memcpy(&received, pData->dataInd.msdu.p, sizeof received);

如果这不能解决问题,则检查复制到发送缓冲区的实际字节和从接收缓冲区复制的字节,并确保它们相同。

【讨论】:

  • 感谢您的回答:PC 上的测试(由 gcc 编译)运行良好(显然)。明天我将在 CC2530 上对其进行测试,看看会发生什么。我没有看到可能的不同对齐方式。这对于 CC2530 一样的内存受限系统是有意义的。
  • 完美运行!刚刚使用了 TI 提供的osal_memcpy。再次感谢您。
【解决方案2】:

为什么不使用定点来表示您的数字?每当我使用 TI CC2530 时,我都试图避免浮点的开销,并采用定点表示数字。这些值在发送时更直接,但您必须小心您的表示。

【讨论】:

  • 您在开销的意义上是完全正确的,但是对于我正在构建的应用程序,我需要使用 float 来保持一定的精度。因为对于这个应用程序,开销并不重要,我不想处理预乘法和除法来保持精度不变。此外,我认为它在复制浮点数时可能会出现同样的问题,导致对齐(虽然 8 位是不够的)。谢谢!
猜你喜欢
  • 2014-06-18
  • 1970-01-01
  • 2021-05-11
  • 2018-02-22
  • 2014-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多