TI CC2530 — преобразовать число с плавающей запятой в uint8[] для отправки, а затем преобразовать обратно в число с плавающей запятой при приеме

Мне нужно отправить несколько чисел с плавающей запятой между некоторыми узлами Texas Instrument 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->dataInd.msdu.p[rec_index]

Симуляция передачи, которую я пробовал на ПК, выглядит следующим образом:

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

В этом случае я вижу, что тест хорошо работает на ПК, но не на узлах. Что случилось?

Спасибо заранее за любую помощь!

Алекс


person Alex Pacini    schedule 05.12.2013    source источник
comment
Может ли принимающая сторона выйти из фазы, чтобы она принимала конечные байты из 1 пакета и начальный байт следующего пакета? Если это возможно, ваши пакеты должны быть увеличены в размере, чтобы включать в себя что-то, чтобы обеспечить правильное выравнивание во время связи.   -  person chux - Reinstate Monica    schedule 06.12.2013
comment
Размера пакета должно быть достаточно для этой области, у меня есть 20-байтовый пакет, а число с плавающей запятой всего 4 байта. Более того, пакет создается, устанавливая данные в правильном месте массива для отправки, что устраняет даже проблему обратного переупорядочения (классическая проблема с последовательными коммуникациями). Спасибо!   -  person Alex Pacini    schedule 06.12.2013


Ответы (2)


Код в разделе приема проблематичен. Вы копируете байты в receiveds, а затем используете преобразования указателя, чтобы рассматривать его как float. Однако во многих реализациях C используется выравнивание по одному байту для типов символ/байт (как, вероятно, receiveds) и выравнивание по четырем байтам для типов float. Преобразование указателя uint8 в указатель float может привести к неправильному выравниванию указателя.

Вместо этого вы можете сделать это:

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

Кроме того, если pData->dataInd.msdu.p является массивом или указателем на байты (char, unsigned char или, скорее всего, uint8 и uint8 являются символьными типами в вашей реализации C), то вы можете не использовать receiveds в качестве промежуточного буфера и просто скопировать напрямую:

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

Если это не решит проблему, проверьте фактические байты, копируемые в буфер отправки, и байты, копируемые из буфера приема, и убедитесь, что они совпадают.

person Eric Postpischil    schedule 05.12.2013
comment
Спасибо за ваш ответ: тест на ПК (составленный gcc) тоже сработал (очевидно). Завтра протестирую на CC2530 и посмотрю что получится. Чего я не видел, так это возможного другого выравнивания. Это имеет смысл для системы с ограниченной памятью, такой как CC2530. - person Alex Pacini; 06.12.2013
comment
Он работает отлично! Просто использовал osal_memcpy, предоставленный TI. Еще раз спасибо. - person Alex Pacini; 06.12.2013

Почему бы не представлять ваши числа с помощью фиксированной точки? Всякий раз, когда я работал с TI CC2530, я пытался избежать накладных расходов, связанных с числами с плавающей запятой, и прибегал к представлению чисел в виде фиксированной точки. Эти значения гораздо более прямолинейны при отправке, но вы должны быть осторожны с их представлением.

person bblincoe    schedule 05.12.2013
comment
Вы совершенно правы в смысле накладных расходов, но для приложения, которое я создаю, мне нужно использовать float, чтобы сохранить определенную точность. Поскольку для этого приложения накладные расходы не важны, я не хотел иметь дело с предварительным умножением и делением, чтобы сохранить постоянную точность. Кроме того, я думаю, что у него может быть та же проблема при копировании, что и у числа с плавающей запятой, из-за выравнивания (однако 8 бит недостаточно). Спасибо! - person Alex Pacini; 06.12.2013