Пробовал разными вариантами объявлять объединение и инициализировать, но все не то: Код (C++): typedef struct PROGMEM { union{ unsigned char uParam[6]; float fParam[2]; }; } DataParam; DataParam mFloat={ (float)-50.0, (float)150.0 }; На последнюю строчку ругается: инициализация: преобразование "float" в "unsigned char", возможна потеря данных Как победить?
Ну все правильно, с каких пор unsigned char стал дробным? И если uParam[6] и fParam[2] то вроде как надо DataParam mFloat={{1,4,8,1,21,99}, {1.1,3.14}}; О и еще увидел typedef struct PROGMEM а точно если уже объявил в PROGMEM то потом можно что то еще делать?
Код (C++): typedef struct DataParam_t { union{ unsigned char uParam[6]; float fParam[2]; }; DataParam_t(float a, float b) { fParam[0] = a; fParam[1] = b; } } DataParam; DataParam mFloat((float)-50.0, (float)150.0);
Инициализатору, заключенному в скобки, доступен только первый член объединения. Можете убедиться поменять местами члены. Код (C++): typedef struct { union{ float fParam[2]; unsigned char uParam[6]; }; } DataParam; DataParam mFloat = { (float)-50.0, (float)150.0 }; Для случая DataParam PROGMEM mFloat это не прокатит, Код (Text): sketch_dec03a:7:19: error: variable 'mFloat' must be const in order to be put into read-only section by means of '__attribute__((progmem))' DataParam PROGMEM mFloat = { ^~~~~~ т.е. инициализатор будет вызываться в коде.
размер данных разного типа в обьединении должен совпадать, иначе компилятор не будет знать, как преобразовать одно в другое. А у вас? Два float - это 4х2 = 8 байт А 6 char - это 6 байт... Сделайте массив char длиной 8 элементов - ошибки не будет.
непосредственно инициализировать унион в прогмеме у меня не получилось, только через промежуточную структуру Но вот так все работает: Код (C++): // описываем union typedef struct DataParam_t { union{ unsigned char uParam[8]; float fParam[2]; }; } DataParam; // описываем вспомогательную структуру, через которую будем инициализировать union typedef struct { float ff[2]; } DataParam_f; // инициализируем const DataParam_f mFloat PROGMEM = { -50.0, 150.0 }; Опять же, обратится к этим данным именно как унион непосредственно из прогмем не выйдет, нужно сначала скопировать их в локальную структуру Код (C++): void setup() { Serial.begin(9600); // выгрузка данныхиз прогмем в локальную структуру DataParam temp_str; memcpy_P( &temp_str, &mFloat, sizeof(DataParam)); Serial.println(temp_str.fParam[0]); } Вывод = если таких данных в программе много - может и имеет смысл, а если один-два экземпляра - то проще в оперативке хранить Если кто может сделать это красивее - показывайте, интересно
ну как раз эту ошибку очень легко обойти, если инициализировать через список Код (C++): typedef struct DataParam_t { union{ const unsigned char uParam[8]; const float fParam[2]; }; DataParam_t(float a, float b): fParam{a,b} {} } DataParam; const DataParam PROGMEM mFloat( -50.0, 150.0 ); все отлично компилируется, только не работает
И еще добавлю - вообще, чтобы обращаться к массиву float ff[2] как в двум флоат или как к восьми байтам - вообще никакой унион не нужен. Достаточно приведения типов. И для случая ПРОГМЕМ это, пожалуй, самый простой и короткий вариант