Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Писать/читать члены структуры генерик способом.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Jenya7
Есть структура с разными данными
CODE
typedef struct MOTOR_DATA_S
{
uint32_t mot_num;
uint32_t mot_ena;
uint32_t sprof_ena;
uint32_t tprof_ena;

//run time
uint32_t state;
uint32_t dir;
uint32_t speed;
int32_t position;
uint32_t current;
uint32_t ovc;

uint32_t soft_start;
uint32_t soft_stop;

//hardware interface
uint32_t lim_sw_fwd;
uint32_t lim_sw_rev;
uint32_t pwm_tim;
uint32_t pwm_num;
uint32_t fwd_pwm_chan;
uint32_t rev_pwm_chan;
uint32_t adc_chan;
uint32_t enc_num;
uint32_t enc_type;

uint32_t start_stop;

//max limits
uint32_t fwd_pwm_run;
uint32_t rev_pwm_run;
uint32_t fwd_max_pos;
uint32_t rev_max_pos;
uint32_t max_current;
uint32_t max_ovc;

SPEED_PROFILE fwd_profile[MAX_PROFILES];
SPEED_PROFILE rev_profile[MAX_PROFILES];
TRAPEZ_PROFILE start_profile;
TRAPEZ_PROFILE stop_profile;

} MOTOR_DATA;

MOTOR_DATA mot_data;


Я пишу читаю члены структуры посредством команд пришедших с терминала. Ну например так
Код
uint32_t COM_Ovc(uint32_t argc, char** args)
{
    uint32_t arguments[argc];
    uint32_t addr_offset;
    
    if (GetIntArguments(argc, args, arguments) == MSG_OK)
    {
        if (ValidateArgument(arguments[0], 0, 0xFFFF))
        {
            if (argc >0)  // argument  - write
            {
                mot_data.max_ovc = arguments[0];
                EE_WriteVariable(EPR_ADR_OVC, arguments[0]);
            }
            else  //no argument - read
                Parser_SendInt(COM_USART, mot_data.max_ovc, 1, 0);
        }
        else
            return MSG_INV_ARG;
    }
    else
        return MSG_MIS_ARG;
    
    return MSG_OK;


В общем все команды одинаковы за исключением mot_data.член_структуры. Получается одна переменная - одна функция.
Для того чтоб написать одну генерик функцию я думал создать указатель на член структуры
Код
uint32_t *ptr;
ptr = &mot_data.max_ovc;
//write
*ptr = arguments[0];
//read
Parser_SendInt(COM_USART, *ptr, 1, 0);

и изменять только его в функции.
но тут возникает вопрос - получается мне нужна еще одна функция которая тупо переберет 20 (или сколько там членов структуры) кейсов и найдет на какой член структуры указывать.
как то получается довольно монструозно и не гибко.
Tiro
Цитата(Jenya7 @ Jul 20 2017, 14:30) *
Есть структура с разными данными
CODE
typedef struct MOTOR_DATA_S
{
uint32_t mot_num;
uint32_t mot_ena;
uint32_t sprof_ena;
uint32_t tprof_ena;

//run time
uint32_t state;
uint32_t dir;
uint32_t speed;
int32_t position;
uint32_t current;
uint32_t ovc;

uint32_t soft_start;
uint32_t soft_stop;

//hardware interface
uint32_t lim_sw_fwd;
uint32_t lim_sw_rev;
uint32_t pwm_tim;
uint32_t pwm_num;
uint32_t fwd_pwm_chan;
uint32_t rev_pwm_chan;
uint32_t adc_chan;
uint32_t enc_num;
uint32_t enc_type;

uint32_t start_stop;

//max limits
uint32_t fwd_pwm_run;
uint32_t rev_pwm_run;
uint32_t fwd_max_pos;
uint32_t rev_max_pos;
uint32_t max_current;
uint32_t max_ovc;

SPEED_PROFILE fwd_profile[MAX_PROFILES];
SPEED_PROFILE rev_profile[MAX_PROFILES];
TRAPEZ_PROFILE start_profile;
TRAPEZ_PROFILE stop_profile;

} MOTOR_DATA;

MOTOR_DATA mot_data;

Структура маленькая, получайте и заполняйте ее целиком, парсить каждую уставку бессмысленно.
Jenya7
Цитата(Tiro @ Jul 20 2017, 17:50) *
Структура маленькая, получайте и заполняйте ее целиком, парсить каждую уставку бессмысленно.

оператор хочет изменить/прочитать один параметр. он в команде передает мне какой.
Tiro
Цитата(Jenya7 @ Jul 20 2017, 15:05) *
оператор хочет изменить/прочитать один параметр. он в команде передает мне какой.

А кто протокол обмена придумал? Изменил один параметр, шлешь все уставки.

P.S. Если нет команды поменять все, то начнется беда. Нужно применить набор новых уставок - будешь менять по одной. Так и вижу, как шлются и парсятся 20+ пакетов на изменение содержимого структуры )) А что, процессор зато занят ))

P.P.S. К тому же писать сразу в ЕЕПРОМ совершенно незачем. Есть и врЕменные уставки.
Jenya7
Цитата(Tiro @ Jul 20 2017, 18:07) *
А кто протокол обмена придумал? Изменил один параметр, шлешь все уставки.

P.S. Если нет команды поменять все, то начнется беда. Нужно применить набор новых уставок - будешь менять по одной. Так и вижу, как шлются и парсятся 20+ пакетов на изменение содержимого структуры )) А что, процессор зато занят ))

P.P.S. К тому же писать сразу в ЕЕПРОМ совершенно незачем. Есть и врЕменные уставки.


Изменил один параметр, шлешь все уставки? Зачем?

вопрос когда записать в ЕЕПРОМ если не сразу?
Tiro
Цитата(Jenya7 @ Jul 20 2017, 15:24) *
Изменил один параметр, шлешь все уставки? Зачем?

А какие противопоказания?

Цитата
вопрос когда записать в ЕЕПРОМ если не сразу?

По команде. Можно и по другим признакам, кол-во перемен или время. Но надо ли?
Команда "сохранить уставки" все решит.
k155la3
Цитата(Jenya7 @ Jul 20 2017, 14:30) *
. . .
но тут возникает вопрос - получается мне нужна еще одна функция которая тупо переберет 20 (или сколько там членов структуры) кейсов и найдет на какой член структуры указывать. как то получается довольно монструозно и не гибко.


Если параметров достаточно много и разных ( а даже - и немного)
имеет смысл все параметры перечислить в некой "базе", и далее работать с ними для записи-чтения по коду (номеру в базе)
Причем при такой методе параметры могут быть самые "разношерстные", а доступ ведется перебором или по номеру-индексу.
Можно создавать списки из различных наборов переменных для записи.

Пишу "все оптом", тк использую флеш, а для нее - что байт, что страница - всеравно.
Код
struct SVarBase
{
    int     VarID;        // уникальный код переменной по e_VarIdCode
    void     * VarPtr;    // адрес переменной
    int        VarType;    // тип переменной по кодификации enum e_TypeVar
                // VarTypes.h
};

typedef const SVarBase TVarBase;


__root TVarBase VarBase[] =
{
  // ------------------- DATA --------------------------
     [eV_MM_Au     ]  = { eV_MM_Au,       &MM_Au,          T_REAL },
     // ----------
     [eV_MM_A1234_0]  = { eV_MM_A1234_0,  &MM_A1234[0],       T_REAL },
     [eV_MM_A1234_1]  = { eV_MM_A1234_1,  &MM_A1234[1],       T_REAL },
. . . .
Jenya7
Цитата(k155la3 @ Jul 20 2017, 18:40) *
Если параметров достаточно много и разных ( а даже - и немного)
имеет смысл все параметры перечислить в некой "базе", и далее работать с ними для записи-чтения по коду (номеру в базе)
Причем при такой методе параметры могут быть самые "разношерстные", а доступ ведется перебором или по номеру-индексу.
Можно создавать списки из различных наборов переменных для записи.

Пишу "все оптом", тк использую флеш, а для нее - что байт, что страница - всеравно.
Код
struct SVarBase
{
    int     VarID;        // уникальный код переменной по e_VarIdCode
    void     * VarPtr;    // адрес переменной
    int        VarType;    // тип переменной по кодификации enum e_TypeVar
                // VarTypes.h
};

typedef const SVarBase TVarBase;


__root TVarBase VarBase[] =
{
  // ------------------- DATA --------------------------
     [eV_MM_Au     ]  = { eV_MM_Au,       &MM_Au,          T_REAL },
     // ----------
     [eV_MM_A1234_0]  = { eV_MM_A1234_0,  &MM_A1234[0],       T_REAL },
     [eV_MM_A1234_1]  = { eV_MM_A1234_1,  &MM_A1234[1],       T_REAL },
. . . .

а ну если так то я могу засунуть указатель в структуру принятой команды
Код
typedef struct COMMAND_S
{
    char *name;  //command name
    uint32_t command_type;
    uint32_t minargs;
    uint32_t maxargs;
    uint32_t (*fp)(unsigned int, char **); //fuction poiner

    //это я добавляю
    uint32_t *vp; //variable pointer
}COMMAND;

я все равно инициализирую структуру команд. так я добавлю указатель на переменную
Код
COMMAND commands[] =
{
    [0] = { "stop",  0, 1, MAX_ARGS, .fp = OneGlobFunc, .vp = NULL },
    [1] = { "start", 0, 1, MAX_ARGS, .fp = OneGlobFunc, .vp = NULL },
    [2] = { "fwd",   0, 1, MAX_ARGS, .fp = OneGlobFunc, .vp = NULL},
    [3] = { "rev",   0, 1, MAX_ARGS, .fp = OneGlobFunc, .vp = NULL},
    [4] = { "mot",   0, 1, MAX_ARGS, .fp = OneGlobFunc, .vp = NULL },
    [5] = { "pfb",   0, 1, MAX_ARGS, .fp = OneGlobFunc, .vp = &mot_data.pfb},
    [6] = { "ifb",   0, 1, MAX_ARGS, .fp = OneGlobFunc, .vp = &mot_data.ifb},
    [7] = { "ftop",  0, 1, MAX_ARGS, .fp = OneGlobFunc  .vp = &mot_data.fwd_max_pos },
    [8] = { "rtop",  0, 1, MAX_ARGS, .fp = OneGlobFunc  .vp = &mot_data.rev_max_pos}
};


ситуация несколько усложнилась. у меня мултиаксис поэтому массив структур mot_data[AXIS_NUM] . то есть мне надо инициализировать так
.vp = &mot_data[AXIS].pfb
проблема что AXIS передается аргументом в команде.
Tiro
Цитата(k155la3 @ Jul 20 2017, 15:40) *
Если параметров достаточно много и разных ( а даже - и немного)
имеет смысл все параметры перечислить в некой "базе", и далее работать с ними для записи-чтения по коду (номеру в базе)
Причем при такой методе параметры могут быть самые "разношерстные", а доступ ведется перебором или по номеру-индексу.

Вот только не понятно зачем по номеру? Для кого придуманы структуры "struct" и объединения "union"?
Они позволяют доступ на этапе связывания (линковки) по адресу. Без функций, номеров и т.п. программазма.

Используете в программе структуру уставок/параметров - отлично. Заменяйте их все одновременно.

Как?
Имейте 3 записи: 1-ЕЕПРОМ, 2-уставки в ОЗУ, 3-рабочие копии в ОЗУ.
Пришла команда - изменяем уставки 2. Подгоняем уставки 3.
Устроили "оператора" - пишем уставки 2 в 1. Иначе зачем они там?

Программирование это не только "coding", это еще и структурирование и декомпозиция т.п. А программизм ради структурирования сродни (сами придумаете).
Jenya7
Цитата(Tiro @ Jul 20 2017, 18:55) *
Вот только не понятно зачем по номеру? Для кого придуманы структуры "struct" и объединения "union"?
Они позволяют доступ на этапе связывания (линковки) по адресу. Без функций, номеров и т.п. программазма.

Используете в программе структуру уставок/параметров - отлично. Заменяйте их все одновременно.

Как?
Имейте 3 записи: 1-ЕЕПРОМ, 2-уставки в ОЗУ, 3-рабочие копии в ОЗУ.
Пришла команда - изменяем уставки 2. Подгоняем уставки 3.
Устроили "оператора" - пишем уставки 2 в 1. Иначе зачем они там?

Программирование это не только "coding", это еще и структурирование и декомпозиция т.п. А программизм ради структурирования сродни (сами придумаете).

изначально я хотел так сделать. поигрался с настройками, все устраивает, нажал SAVE - настройки записались в EEPROM . Оператор забывал про SAVE . Я отменил SAVE.
Tiro
Цитата(Jenya7 @ Jul 20 2017, 16:07) *
Я отменил SAVE.

МолодЕц. Дальше и огребай последствия своего решения.
Jenya7
что то я туплю. как там математика с указателями? если массиив - mot_data + sizeof(mot_data)*array_index + struct_member - как это разрулить?
.vp = struct_member а array_index я получу в команде
Tiro
Цитата(Jenya7 @ Jul 20 2017, 16:17) *
что то я туплю. как там математика с указателями? если массиив - mot_data + sizeof(mot_data)*array_index + struct_member - как это разрулить?
.vp = struct_member а array_index я получу в команде

Зачем? mot_data.mot_num и т.д. Используйте возможности компилятора и имена.
Jenya7
Цитата(Tiro @ Jul 20 2017, 19:23) *
Зачем? mot_data.mot_num и т.д. Используйте возможности компилятора и имена.

мне нужно динамически получить адрес - mot_data[INDEX].mot_num. INDEX - я получаю динамически в run time
Tiro
Цитата(Jenya7 @ Jul 20 2017, 16:28) *
мне нужно динамически получить адрес - mot_data[INDEX].mot_num. INDEX - я получаю динамически в run time

Если не массив не в "heap", а выделен явно, так и пиши mot_data [i].mot_num и т.п. где i твой индекс
k155la3
Цитата(Tiro @ Jul 20 2017, 15:55) *
(1) Вот только не понятно зачем по номеру? . . .
(2) . . . Заменяйте их все одновременно.
(3) Программирование это не только "coding", это еще и структурирование и декомпозиция т.п. А программизм ради структурирования сродни (сами придумаете).

(1) одна из многих причин - обмен данными прибора и PC. Чтобы избежать "шизофрении" - на порядок удобнее работать с кодом параметра
(фактически его уникальным Id) и базой параметров. Для "синхронизации" проектов для прибора и PC достаточно чтобы они использовали
один файл - базы, где указано соотв-ие параметра, его Id, тип_данных --> размер поля итд.
Для "упаковки" в пакет или страницу флеш использую сериализацию. Это надежнее.
(2) пока все парам. влазят в страницу (264 байта) - я так и делаю.
(3) да sm.gif

Я привел пример только как один из многих-бесконечных вариантов реализации.
ps - структуры отличное решение, еслиб...... не выравнивание, а темболее - для разных платформ. А также зависимость от опций компилятора.




Цитата(Jenya7 @ Jul 20 2017, 15:44) *
а ну если так то я могу засунуть указатель в структуру принятой команды
. . . .
я все равно инициализирую структуру команд. так я добавлю указатель на переменную

Да, где-то так. У меня по такой идее постоены работа HMI прибора - меню и работа с внешним терминалом по USART.
По меню проскакивало обсуждение, тег кажется micromenu.
Tiro
Цитата(k155la3 @ Jul 20 2017, 16:46) *
(1) одна из многих причин - обмен данными прибора и PC. Чтобы избежать "шизофрении" - на порядок удобнее работать с кодом параметра
(фактически его уникальным Id) и базой параметров. Для "синхронизации" проектов для прибора и PC достаточно чтобы они использовали
один файл - базы, где указано соотв-ие параметра, его Id, тип_данных --> размер поля итд.
Для "упаковки" в пакет или страницу флеш использую сериализацию. Это надежнее.

Этот аргумент хорош для придания совместимости с ранее разработанными приборами.
И при этом все равно лучше передавать блок параметров.
Заметьте, что сериализация все равно машиннозависимая. Если слать параметры и размеры, то это то, от чего хотел уйти.
(2) пока все парам. влазят в страницу (264 байта) - я так и делаю.
Цитата(k155la3 @ Jul 20 2017, 16:46) *
Я привел пример только как один из многих-бесконечных вариантов реализации.
ps - структуры отличное решение, еслиб...... не выравнивание, а темболее - для разных платформ. А также зависимость от опций компилятора.

Вот с выравниванием тут хорошо. Я сказал "передавать блок параметров", рассортируйте по адресам.
Jenya7
еще раз
uint32_t *base_ptr;
base_ptr = mot_data+(sizeof(mot_data)*array_index);
как мне динамически передать struct_member - base_ptr->struct_member

хотя нет. sizeof возращает размер в байтах значит надо приводить к uint8_t?
uint8_t *base_ptr = mot_data+(sizeof(mot_data)*array_index)
Kabdim
siplasplas
Tiro
Цитата(Jenya7 @ Jul 20 2017, 16:59) *
еще раз
uint32_t *base_ptr;
base_ptr = mot_data+(sizeof(mot_data)*array_index);
как мне динамически передать struct_member - base_ptr->struct_member

Если правильно понял, то достаточно прочесть Карнегина и Ричина. После присвоения base_ptr = mot_data без твоих выражений доступ по base_ptr[array_index].mot_number
Jenya7
Цитата(Tiro @ Jul 20 2017, 20:07) *
Если правильно понял, то достаточно прочесть Карнегина и Ричина. После присвоения base_ptr = mot_data без твоих выражений доступ по base_ptr[array_index].mot_number

это не base_ptr[array_index].mot_number - это base_ptr[array_index].зависит_от_команды_пришедшей_по_терминалу - мне надо чтоб указатель указывал на base_ptr[array_index].зависит_от_команды_пришедшей_по_терминалу
Tiro
Цитата(Jenya7 @ Jul 20 2017, 17:18) *
это не base_ptr[array_index].mot_number - это base_ptr[array_index].зависит_от_команды_пришедшей_по_терминалу - мне надо чтоб указатель указывал на base_ptr[array_index].зависит_от_команды_пришедшей_по_терминалу

Если Вас не устраивает предложенный вариант, то для Вас придуман С++14. А так - придумайте команды терминала, соответствующие задаче.
k155la3
Цитата(Jenya7 @ Jul 20 2017, 16:59) *
uint32_t *base_ptr;
base_ptr = mot_data+(sizeof(mot_data)*array_index);
как мне динамически передать struct_member - base_ptr->struct_member

может offsetof(x,y) ?
И зачем динамически, ОНОж вроде, константа ?
ps - смещения offsetof(x,y) занесите в массив - "описатель" структуры.
Tiro
Цитата(k155la3 @ Jul 20 2017, 17:24) *
может offsetof(x,y) ?
И зачем динамически, ОНОж вроде, константа ?

Судя по записи выше, предложена перегрузка оператора функцией. С++ Жене в руки. И удачи.
Jenya7
можно так
при инициализации
.vp = &mot_data[0].член_структуры
и потом в команде полчили AXIS
и прибавили AXIS * sizeof(mot_data)
не очень мне это нравиться, но...
Tiro
Цитата(Jenya7 @ Jul 20 2017, 17:36) *
&mot_data[0].член_структуры
и
base_ptr[array_index].зависит_от_команды_пришедшей_по_терминалу

Одна сущность или разные? Первая - статический член структуры, второе - перегруженный оператор. Определись.
Jenya7
Цитата(k155la3 @ Jul 20 2017, 20:24) *
может offsetof(x,y) ?
И зачем динамически, ОНОж вроде, константа ?
ps - смещения offsetof(x,y) занесите в массив - "описатель" структуры.

а да? offsetof(структура, член) вернет офсет члена в структуре?

Цитата(Tiro @ Jul 20 2017, 20:44) *
Одна сущность или разные? Первая - статический член структуры, второе - перегруженный оператор. Определись.

ну что то должно быть статическим. либо &mot_data[0].член_структуры, либо offsetof(структура, член) если это работает.
Tiro
Цитата(Jenya7 @ Jul 20 2017, 17:47) *
а да? offsetof(структура, член) вернет офсет члена в структуре?
ну что то должно быть статическим. либо &mot_data[0].член_структуры, либо offsetof(структура, член) если это работает.

Компилятор = переводчик с русского на машинный. Учитесь выражаться.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.