Программирование ARM ESP-IDF: преобразование 32-битных чисел float в 16-битные значения Thu, March 05 2026  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


ESP-IDF: преобразование 32-битных чисел float в 16-битные значения Печать
Добавил(а) microsin   

Иногда бывает необходимо для экономии пропускной способности преобразовать 32-битные значения float в 16-битные данные. Например, когда заранее известно, что 32-битный float содержит значения с точностью не более 16 бит. К сожалению, в ESP-IDF нет встроенной поддержки float16_t. Но есть несколько обходных практических решений.

Для экономии места при передаче данных вы можете использовать 16-битные числа с плавающей запятой, но в ESP-IDF нет встроенной поддержки float16_t. Вот несколько практических решений:

Вариант 1: Прямое масштабирование в целые числа. Это самый простой и эффективный способ. Предположим, изначально было исходное значение:

float valf = 123.45; // 32-битное значение с плавающей запятой.

Если мы заранее знаем, что это значение не превышает 327, то его можно преобразовать в 16-битное значение путем домножения на 100:

// На стороне передачи по радиоканалу:
int16_t v16_scaled = (int16_t)(valf * 100); // 123.45 -> 12345

На стороне приема можно получить обратно число float с точностью 0.01 следующим образом:

float v16 = v16_scaled / 100.0f;  // 12345 -> 123.45

Плюсы:

- Простота и надежность
- Точность до 0.01 (часто такая точность бывает достаточна)
- Минимальные накладные расходы

Вариант 2: Использование библиотеки half-precision float. Если вам нужен именно формат IEEE 754 half-precision:

// Подключите библиотеку half (нужно установить отдельно)
#include "half.hpp" // https://github.com/eliasdaler/half
half_float::half v16; // 2 байта

На ESP32 придется реализовать конвертацию вручную или портировать небольшую библиотеку.

Вариант 3: Собственная реализация half-float. Пример минимальной реализации:

// Преобразование float -> 16 бит (упрощенно)
uint16_t float_to_float16(float f) {
uint32_t f32 = *(uint32_t*)&f;
uint16_t f16 = (f32 >> 16) & 0xFFFF; // Берем старшие 16 бит
return f16; }

// Преобразование 16 бит -> float
float float16_to_float(uint16_t f16) {
uint32_t f32 = ((uint32_t)f16) << 16; // Расширяем до 32 бит
return *(float*)&f32; }

Фактически Вариант 3 это использование чисел с фиксированной запятой (см. [1]).

[Ссылки]

1. AVR - как избавиться от чисел с плавающей точкой.
2. Поддержка традиционных типов с фиксированной точкой в VisualDSP++.

 

Добавить комментарий


Защитный код
Обновить

Top of Page