IEEE-754 отображение float

weary
Offline
Зарегистрирован: 19.01.2018

Добрый день,

Подскажите по конвертации, имеем 4 байта 0x436b580e, по правилам IEEE-754 в DEC float должно быть 235.344. Как заставить float заставить отобразить правильно это число? Пробую разные варианты получается 1131108352.00

 

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Побуду Дедом Морозом.


void setup() {
  uint32_t nInteger;
  float* ptrFloat;

  Serial.begin(9600);

  nInteger = 0x436b580e;
  ptrFloat = (float*) &nInteger;

  Serial.println(*ptrFloat, 3);
}

void loop() {}

 

weary
Offline
Зарегистрирован: 19.01.2018

Супер! спасибо большое. Не хватало этой float* ptrFloat звездочки у меня. А что она значит? когда используется?

Коль такая новогодняя шара, спрошу еще, если у  меня два uint16_t, как лучше их объединить? чтобы конвертировать во float

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

weary пишет:

Супер! спасибо большое. Не хватало этой float* ptrFloat звездочки у меня. А что она значит? когда используется?

 

https://prog-cpp.ru/c-pointers/

Цитата:
Коль такая новогодняя шара, спрошу еще, если у  меня два uint16_t, как лучше их объединить? чтобы конвертировать во float

Зависит от того что и как в этих uint16_t хранится.  Например если сделать так:

    uint16_t s1 = 0x1234;
    uint16_t s2 = 0x5678;
    uint32_t l = s1 << 16 | s2;

То в l получим 0x12345678

sadman41
Offline
Зарегистрирован: 19.10.2016

weary пишет:

если у  меня два uint16_t, как лучше их объединить? чтобы конвертировать во float

Чую запах модбаса, который несёт данные с электросчётчика. Что за модель?

typedef union {
  uint16_t u16[2];
  uint32_t u32;
  float    flt;
} convertor_t;

void setup() {
  Serial.begin(9600);

  convertor_t convertor;
  uint16_t swap;

  convertor.u16[0x00] = 0x436b;
  convertor.u16[0x01] = 0x580e;

  Serial.print("UINT_32 (1): 0x"); Serial.println(convertor.u32, HEX);

  swap = convertor.u16[0x00];
  convertor.u16[0x00] = convertor.u16[0x01];
  convertor.u16[0x01] = swap;

  Serial.print("UINT_32 (2): 0x"); Serial.println(convertor.u32, HEX);
  Serial.print("FLOAT      : ");   Serial.println(convertor.flt, 3);
}

void loop() {}

 

weary
Offline
Зарегистрирован: 19.01.2018

sadman41 пишет:

weary пишет:

если у  меня два uint16_t, как лучше их объединить? чтобы конвертировать во float

Чую запах модбаса, который несёт данные с электросчётчика. Что за модель?

typedef union {
  uint16_t u16[2];
  uint32_t u32;
  float    flt;
} convertor_t;

void setup() {
  Serial.begin(9600);

  convertor_t convertor;
  uint16_t swap;

  convertor.u16[0x00] = 0x436b;
  convertor.u16[0x01] = 0x580e;

  Serial.print("UINT_32 (1): 0x"); Serial.println(convertor.u32, HEX);

  swap = convertor.u16[0x00];
  convertor.u16[0x00] = convertor.u16[0x01];
  convertor.u16[0x01] = swap;

  Serial.print("UINT_32 (2): 0x"); Serial.println(convertor.u32, HEX);
  Serial.print("FLOAT      : ");   Serial.println(convertor.flt, 3);
}

void loop() {}

 

 

 

Да, в точку)) DDS578R в пути еще, пока по мануалу разбираюсь. Прикрутить к домашней сети модбас хочу

weary
Offline
Зарегистрирован: 19.01.2018

asam пишет:

weary пишет:

Супер! спасибо большое. Не хватало этой float* ptrFloat звездочки у меня. А что она значит? когда используется?

 

https://prog-cpp.ru/c-pointers/

Цитата:
Коль такая новогодняя шара, спрошу еще, если у  меня два uint16_t, как лучше их объединить? чтобы конвертировать во float

Зависит от того что и как в этих uint16_t хранится.  Например если сделать так:

    uint16_t s1 = 0x1234;
    uint16_t s2 = 0x5678;
    uint32_t l = s1 << 16 | s2;

То в l получим 0x12345678

 

 

По указателю прочитал, спасибо, доходчиво написано. А то по звездочки не гуглилось.

А по преобразованию также хотел сделать, но нужно проверять.

А то, что sadman41 написал, нужно разбираться. для меня там много не очевидных вещей.

 

sadman41
Offline
Зарегистрирован: 19.10.2016

weary пишет:

Да, в точку)) DDS578R в пути еще, пока по мануалу разбираюсь. Прикрутить к домашней сети модбас хочу

Ну, удачи. У меня был такой опыт со счётчиком.

Своп регистров понадобится, если все регистры пачкой принять, а потом во флоаты конвертить. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

weary пишет:

 если у  меня два uint16_t, как лучше их объединить? чтобы конвертировать во float

Через union. И конвертировать ничего не надо.

weary
Offline
Зарегистрирован: 19.01.2018

sadman41 пишет:

weary пишет:

Да, в точку)) DDS578R в пути еще, пока по мануалу разбираюсь. Прикрутить к домашней сети модбас хочу

Ну, удачи. У меня был такой опыт со счётчиком.

Своп регистров понадобится, если все регистры пачкой принять, а потом во флоаты конвертить. 

 

Опыт положительный или оказалось игрушкой? 

Принимать, конечно, пачкой планирую. А свап в смысле просто старший и младший местами менять или Swap endianness

sadman41
Offline
Зарегистрирован: 19.10.2016

weary пишет:
Опыт положительный или оказалось игрушкой?
Я не себе в дом делал. А так - система работает, графики рисует в мониторинге.
weary пишет:
Принимать, конечно, пачкой планирую. А свап в смысле просто старший и младший местами менять или Swap endianness
Мне достаточно было поменять четный регистр с нечётным и посмотреть на эту пачку через структуру, которая всё сама разложила на метрики.

weary
Offline
Зарегистрирован: 19.01.2018

sadman41 пишет:

weary пишет:

если у  меня два uint16_t, как лучше их объединить? чтобы конвертировать во float

Чую запах модбаса, который несёт данные с электросчётчика. Что за модель?

typedef union {
  uint16_t u16[2];
  uint32_t u32;
  float    flt;
} convertor_t;

void setup() {
  Serial.begin(9600);

  convertor_t convertor;
  uint16_t swap;

  convertor.u16[0x00] = 0x436b;
  convertor.u16[0x01] = 0x580e;

  Serial.print("UINT_32 (1): 0x"); Serial.println(convertor.u32, HEX);

  swap = convertor.u16[0x00];
  convertor.u16[0x00] = convertor.u16[0x01];
  convertor.u16[0x01] = swap;

  Serial.print("UINT_32 (2): 0x"); Serial.println(convertor.u32, HEX);
  Serial.print("FLOAT      : ");   Serial.println(convertor.flt, 3);
}

void loop() {}

 

sadman41, перечитал кучу заметок касаемо union, но так до меня и не доходит, как элемет convertor.u32 получается последовательность двух предыдущих элементов и как convertor.flt преобразуется именно из элемента convertor.u32.

Может не там читаю, тогда буду благодарен за ссылку на источник.

sadman41
Offline
Зарегистрирован: 19.10.2016

weary пишет:

Может не там читаю, тогда буду благодарен за ссылку на источник.

Одна и та же область памяти (4 байта) рассматривается или как uint32_t или как float или как массив uint16_t[2]. То, как компилятор её интерпретирует - зависит от указания имени члена объединения.

Пишем convertor.flt - компилятор рассматривает 4 байта, как float, convertor.u32 - как uint32_t и т.п. То же самое приведение типов указателя, как и в первом примере, только скрытое.

Картинку нашёл только такую:

 

weary
Offline
Зарегистрирован: 19.01.2018

Спасибо за информацию.

А uint32_t получается можно вообще убрать?

А typedef нужен только для подмены имени типа union?

sadman41
Offline
Зарегистрирован: 19.10.2016

Можно и убрать, если не нужен для контроля. Использовать typedef - это моя личная заморочка(привычка).

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

можно и так, без typedef

using TVar = union {
	uint8_t 	Bytes[4];
	uint16_t	Words[2];
	uint32_t	DWord;
	float		Float;
};

TVar Variable;
.
.
.
	Variable.Float = PI;

	Serial << "PI = " << Variable.DWord << eoln;