Перейти к содержанию
    

struct - непонятка с косвенной адресацией

Ага, только работать не будет (int по адресу 0x40003002).

Честное слово, не могу понять, что Вам нужно получить в результате - структуру меню с возможностью загрузки из EEPROM? Зачем эти фиксированные адреса и прочие извращения?

 

 

Имеется большое количество переменных. Я хочу как можно сильней упростить их перезапись (в том числе и в ПЗУ).

 

Например писать:

BaudRate = Read_Eprom(10);

StopBit = Read_Eprom(11); и так сто раз весьма утомительно.

 

Вариант с адресацией, на мой взгляд, избавит от рутины, к тому же имена переменных будут осмысленны, в отличие от массива.

Может есть какие-то отлаженные решения?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Имеется большое количество переменных. Я хочу как можно сильней упростить их перезапись (в том числе и в ПЗУ).

 

Например писать:

BaudRate = Read_Eprom(10);

StopBit = Read_Eprom(11); и так сто раз весьма утомительно.

 

Вариант с адресацией, на мой взгляд, избавит от рутины, к тому же имена переменных будут осмысленны, в отличие от массива.

Может есть какие-то отлаженные решения?

как я понимаю, фактически Вы хотите кешировать в ОЗУ некий набор параметров, хранящийся в NVRAM.

в таком случае если структура конфигурации сложная, то необходимо оформить ее в виде структуры, и читатьиз NVRAM блоком примерно как Вы и собирались (путем приведения типа указателя), только я бы оформил такое чтение отдельной функцией. если же параметры конфигурации однотипные, и Вы всего лишь желаете их поименовать по-разному, объявляйте массив и адресуйте его элементы через enum.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Структура, все элементы которой имеют одинаковый тип, явно напрашивается на то, чтобы быть массивом.
Вовсе нет. Смотрите:
typedef struct
{
    uint8_t Size_X;
    uint8_t Size_Y;
    uint8_t Bitmap[];
}  bmp_font_t;

Здесь Size_X и Size_Y имеют такой же тип, что и члены следующего за ними массива, но включать их в этот массив было бы очень ненаглядно.

Как я понял, автор вопроса хранит в структуре данные, которые хоть и имеют один и тот же интегральный тип, но логически не эквивалентны. Если я не прав, то красивым и верным будет решение, предложенное vmp, если же я прав, то подход автора в осмысленным именовании каждого члена безусловно правильный, а для удобства на каких-то операциях работать со структурой как с массивом можно использовать union:

typedef union 
{
    struct
    {
        uint8_t member1;
        uint8_t member2;
        uint8_t member3;
    };
    uint8_t   Array[1];
} setup_t

использование здесь массива размером 1 является некоторым хаком чтобы не именовать структуру. При проверке индекса массива нужно использовать sizeof() от union. Если структуре дать имя, тогда можно в качестве размера массива задать sizeof() структуры, но в коде при доступе к членам появляется в общем-то ненужное имя структуры.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вовсе нет. Смотрите:
typedef struct
{
    uint8_t Size_X;
    uint8_t Size_Y;
    uint8_t Bitmap[];
}  bmp_font_t;

Здесь Size_X и Size_Y имеют такой же тип, что и члены следующего за ними массива, но включать их в этот массив было бы очень ненаглядно.

Как я понял, автор вопроса хранит в структуре данные, которые хоть и имеют один и тот же интегральный тип, но логически не эквивалентны. Если я не прав, то красивым и верным будет решение, предложенное vmp, если же я прав, то подход автора в осмысленным именовании каждого члена безусловно правильный, а для удобства на каких-то операциях работать со структурой как с массивом можно использовать union:

typedef union 
{
    struct
    {
        uint8_t member1;
        uint8_t member2;
        uint8_t member3;
    };
    uint8_t   Array[1];
} setup_t

использование здесь массива размером 1 является некоторым хаком чтобы не именовать структуру. При проверке индекса массива нужно использовать sizeof() от union. Если структуре дать имя, тогда можно в качестве размера массива задать sizeof() структуры, но в коде при доступе к членам появляется в общем-то ненужное имя структуры.

 

Вообще-то типы переменных разные, но для упрощения я их привел к одному типу, нехваткой памяти я не жалуюсь...

 

Простите за серость, но адресацию элементов через enum я еще не делал...

Pls, не подскажете ли конструкцию???

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вообще-то типы переменных разные, но для упрощения я их привел к одному типу, нехваткой памяти я не жалуюсь...

 

Простите за серость, но адресацию элементов через enum я еще не делал...

Pls, не подскажете ли конструкцию???

если разные, делайте как делали, это правильно

по поводу enum:

const u8 CONFIG_SIZE = 3;
enum Config_Items { baud_rate = 0, parity, stop_bits }; // и т.д. - по необходимости
typedef u8 Configuration[CONFIG_SIZE];
Configuration my_config;

for (int i = 0; i < CONFIG_SIZE; ++i)
    my_config[i] = Read_EEEPROM(i);

...

Set_UART(my_config[baud_rate], my_config[parity], my_config[stop_bits]);
...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

union {

unsigned char mass[10];

struct

{

unsigned char Num;

unsigned char Rate;

unsigned char Baud;

unsigned char Led;

unsigned char P4;

unsigned char P5;

unsigned char P6;

unsigned char P7;

unsigned char P8;

struct {

unsigned char bit0:1;

unsigned char bit1:2;

unsigned char bit2:3;

} bits;

} rec;

} eeprom;

 

eeprom.rec.Num=0;

for(u=0;u<sizeof(eeprom);u++)

eeprom.mass=0;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

по поводу enum:

 

не хорошо, так как заставляет сами заниматься преобразование типов

 

 

 

/* Читаем из flash все в память */

void ReadFlashToRam(void)

{

unsigned int i;

unsigned char *data;

 

data=(unsigned char *)&Flash;

for(i=0;i<sizeof(Flash);i++)

data=EEpromRead(i);

};

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость MALLOY2
Господа, что-то не понимаю следующего:

 

Даю описание структуры

 

typedef struct SettingMenu

{

unsigned int

P1,

P2,

...

...

P100;

} Setup;

 

Где-то в модуле(да неважно где) создаем новую структуру типа Setup

 

Setup LocalSetup;

 

Требуется заполнить поля структуры какими-нибудь значениями. Так как количество полей большое, резонно использовать косвенную адресацию.

Берем адрес структуры и в цикле запихиваем в структуру данные.

 

Setup LocalSetup;// Создаем структуру типа Setup

Setup *sptr;// Указатель

...

...

 

sptr = & LocalSetup;// Определяем адрес структуры

 

for (c=0; c<100; c++)

{

*sptr = c; // Записываем по адресу некое значение

sptr++; // Увеличиваем адрес

}

 

Это классический пример С, значения пишутся во все поля без проблем

 

В Keil-е номер не проходит - ругается на разные типы данных строки *sptr = c, хотя теоретически я получил в качестве адреса структуры адрес первого поля этой структуры.

Как бы это правильно разрулить???

 

Я всегда делал так.

Setup LocalSetup;     // Создаем структуру типа Setup
char  *sptr;// Указатель на char (Если структра выровнена по памяти можно и другие типы использовать для более быстрого доступа все зависит от типа CPU и его команд)

sptr = (char*)&LocalSetup;// Определяем адрес структуры
for (c=0; c<sizeof(Setup); c++)  *sptr++ = 0x00; // Записываем по адресу некое значение

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость MALLOY2

А если такая ситуация :)

for (c=0; c<sizeof(Setup); c++)  *sptr++ = get_eeprom(BASE_IMAGE+c); // Записываем по адресу некое значение

 

P.S. А првельней мне кажеться

Read_eeprom(BASE_IMAGE, sptr, sizeof(Setup)); //:)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Итак, общими усилиями получилось следующее:

имеется некая структура типа setup (все-таки структура а не массив, т.к. типы данных разные )

 

typedef struct SettingMenu
{
   char Parametr1;
   char Parametr2;
   int    Parametr3;
   char Array[10];
   float Parametr5;
   ..........

};Setup
..........
..........
Setup LocalSetup;// Структура
char  *sptr; // Указатель


sptr = (char*)&LocalSetup;// Получили адрес
a=sizeof(Setup);// и размер

for (c=0; c<a; c++) 
{
    *sptr++ = ReadEprom(StartSetupAdress+c);
}

 

 

Работает отлично, заморочек с чтением/записью разных типов данных нет. Большое спасибо!!

 

Но, допустим, мне необходимо перезаписать всего один элемент структуры - пускай 5 элемент.

Мне нужно узнать его адрес и размерность.

 

Указано явно:

sptr = (char*)&LocalSetup.Parametr5;
a = sizeof(LocalSetup.Parametr5);// Получили размерность, например, он float - 4 байта
for (c=0; c<a; c++) 
{
    *sptr++ = ReadEprom(StartSetupAdress+N+c);// где N-адрес в ПЗУ Параметра 5
}

 

Такой вопрос: как это сделать не с явным указанием, а по номеру элемента структуры

например, ReadSinglePar(LocalSetup,5), где 5 - пятый элемент структуры, т.е. Parametr5 ?

 

Если это делать явно, то модуль установочного меню раздуется весьма ощутимо, и будет проблемка синхронизации при изменении самой структуры(при изменении количества или названия элементов).

Можно, конечно, переписать всю структуру, но критично время.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Итак, общими усилиями получилось следующее:

[..]

Работает отлично, заморочек с чтением/записью разных типов данных нет. Большое спасибо!!

я бы на Вашем месте еще оформил чтение блока памяти как функцию, тогда программа приобрела бы законченый вид. типа, Read_EEPROM((u8 *)&config, MEM_ADDR, sizeof(config));

 

Но, допустим, мне необходимо перезаписать всего один элемент структуры - пускай 5 элемент.

Мне нужно узнать его адрес и размерность.

для этого есть макросы sizeof() и offsetof()

например:

Read_EEPROM((u8 *)&config.info_1, MEM_ADDR + offsetof(Config_Type, info_1), sizeof(config.info_1));

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

я бы на Вашем месте еще оформил чтение блока памяти как функцию, тогда программа приобрела бы законченый вид. типа, Read_EEPROM((u8 *)&config, MEM_ADDR, sizeof(config));

для этого есть макросы sizeof() и offsetof()

например:

Read_EEPROM((u8 *)&config.info_1, MEM_ADDR + offsetof(Config_Type, info_1), sizeof(config.info_1));

 

Уже сделал, большое спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...