Реклама на сайте DatasheetsDatasheets

KAZUS.RUN - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Книги и журналы
FAQ по электронике

  Datasheets
Поиск SMD
Онлайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Схемы и проекты
Принципиальные схемы
  Программы
Каталог сайтов
Калькуляторы
  Форумы по электронике
Помощь проекту

Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей...

 
Опции темы

Как получить адрес элемента структуры?

Непрочитано 13.11.2011, 00:13  
k0stya_
Временная регистрация
 
Регистрация: 23.09.2007
Адрес: Кривой Рог, Украина
Сообщений: 55
Сказал спасибо: 34
Сказали Спасибо 34 раз(а) в 20 сообщении(ях)
k0stya_ на пути к лучшему
Вопрос Как получить адрес элемента структуры?

Пишу программу на Си (WinAVR) для ATmega8 и вот сталкнулся с такой проблемой.

Есть структура

Код:
struct dataexchange         // Описание структуры для передачи данных
{
  unsigned char cmd;         // Код команды, которую нужно выполнить.
  unsigned char adr1;        // Адрес, используется в некоторых командах (старший байт).
  unsigned char adr2;        // Адрес, используется в некоторых командах (младший байт).
  unsigned char dat1;        // Данные, относящиеся к команде (первый байт).
  unsigned char dat2;        // Данные, относящиеся к команде (второй байт).
};
 
struct dataexchange pdata = {0, 0, 0, 0, 0};
В процессе работы нужно записывать/считывать данные в/из EEPROM. В библиотеке WinAVR указаны сигнатуры

Код:
/** \ingroup avr_eeprom
    Read one byte from EEPROM address \a __p.
 */
uint8_t eeprom_read_byte (const uint8_t *__p) __ATTR_PURE__;

/** \ingroup avr_eeprom
    Write a byte \a __value to EEPROM address \a __p.
 */
void eeprom_write_byte (uint8_t *__p, uint8_t __value);
Я делаю так

Код:
eeprom_write_byte (&pdata.adr1, pdata.dat1); // Записываем

pdata.dat1 = eeprom_read_byte (&pdata.adr1); // Считываем
и при этом данные записываются и счиваются только в одной ячейке по адресу 0x0064, т.е. адрес вычесляется неверно.
Искал в google, заглянул в пару книг по Си но везде указано только как получить адресс самой структуры и дальше с помощью оператора -› обращаться к элементам, но мне это не подходит, т.к. нужно передать адрес самого элемента.

Прошу помочь.
Реклама:

Последний раз редактировалось k0stya_; 15.11.2011 в 23:53.
k0stya_ вне форума  
Сказали "Спасибо" k0stya_
warel (28.06.2019)
Непрочитано 13.11.2011, 01:09  
kison
Почётный гражданин KAZUS.RUN
 
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
kison на пути к лучшему
По умолчанию Re: Как получить адрес элемента структуры?

&pdata.adr1 - правильный способ. Дает указатель на элемент структуры.
Вам надо с записью разобраться. Ответить себе на пару вопросов - например что такое adr1. Скорее всего ответ будет - адрес куда писать в еепром. По сути - указатель. Так наверно и надо передавать не указатель на указатель, а само значение.
eeprom_write_byte ((void*)pdata.adr1, pdata.dat1); // Записываем
Возможно я конечно не понял цель. Что хотим получить то?
kison вне форума  
Эти 2 пользователя(ей) сказали Спасибо kison за это сообщение:
k0stya_ (13.11.2011), warel (28.06.2019)
Непрочитано 13.11.2011, 01:44  
Yurkin2007
Заблокирован
 
Регистрация: 27.03.2007
Сообщений: 1,327
Сказал спасибо: 12
Сказали Спасибо 576 раз(а) в 460 сообщении(ях)
Yurkin2007 на пути к лучшему
По умолчанию Re: Как получить адрес элемента структуры?

Сообщение от k0stya_ Посмотреть сообщение
данные записываются и счиваются только в одной ячейке по адресу 0x0064,
Ну, всё правильно. Вот, смотрите. Вы объявили переменную pdata, которая есть структура. При компилировании программы компилятор разместил эту переменную в памяти RAM процессора так, что элемент cmd этой переменной лежит по адресу 0x0063, элемент adr1 по адресу 0x0064, элемент adr2 по адресу 0x0065 и т.д. Причем эти адреса - константы и не изменяются при работе программы, то есть переменную pdata как положили в память, так она там и лежит, не двигаясь ...
Поэтому запись &pdata.adr1 = 0х0064 всегда.
Если же Вы хотите писать куда-то по адресу, который лежит в ячейках adr1,adr2, то нужно использовать значения этих элементов, а не их адреса. Как я понял, adr1 - старший байт нужного адреса записи, а adr2 - младший. Тогда полный адрес будет = (adr1 ‹‹ 8 ) + adr2. И ещё нужно сказать компилятору, что по этому адресу будет записан беззнаковый байт uint8_t.
То есть, получается так:
Код:
;
eeprom_write_byte ((uint8_t *)((pdata.adr1‹‹8)+pdata.adr2), pdata.dat1);
;

Последний раз редактировалось Yurkin2007; 13.11.2011 в 01:50.
Yurkin2007 вне форума  
Эти 2 пользователя(ей) сказали Спасибо Yurkin2007 за это сообщение:
k0stya_ (13.11.2011), warel (28.06.2019)
Непрочитано 13.11.2011, 11:39  
nonamedov
Почётный гражданин KAZUS.RUN
 
Регистрация: 06.06.2008
Сообщений: 1,519
Сказал спасибо: 76
Сказали Спасибо 427 раз(а) в 365 сообщении(ях)
nonamedov на пути к лучшему
По умолчанию Re: Как получить адрес элемента структуры?

Думаю, проблема в приоритете операций, приоритет операции взятие ссылки & ниже чем операции обращения к полю ., поэтому надо писать так: (&pdata).adr1.
nonamedov вне форума  
Сказали "Спасибо" nonamedov
warel (28.06.2019)
Непрочитано 13.11.2011, 11:46  
k0stya_
Временная регистрация
 
Регистрация: 23.09.2007
Адрес: Кривой Рог, Украина
Сообщений: 55
Сказал спасибо: 34
Сказали Спасибо 34 раз(а) в 20 сообщении(ях)
k0stya_ на пути к лучшему
По умолчанию Re: Как получить адрес элемента структуры?

Фух, разобрался.
Спасибо Yurkin2007 и kison за помощь.

Все заработало в таком вот виде:
Код:
pdata.dat1 = eeprom_read_byte ((uint8_t *)pdata.adr1); // Считываем

eeprom_write_byte ((uint8_t *)pdata.adr1, pdata.dat1); // Записываем
Выходит операция взятия адреса была лишней и я все время получал указатель на указатель.
k0stya_ вне форума  
Сказали "Спасибо" k0stya_
warel (28.06.2019)
Непрочитано 14.11.2011, 01:23  
_Артём_
Гражданин KAZUS.RUN
 
Регистрация: 16.03.2011
Сообщений: 486
Сказал спасибо: 8
Сказали Спасибо 131 раз(а) в 116 сообщении(ях)
_Артём_ на пути к лучшему
По умолчанию Re: Как получить адрес элемента структуры?

Сообщение от k0stya_ Посмотреть сообщение
Фух, разобрался.
Спасибо Yurkin2007 и kison за помощь.

Все заработало в таком вот виде:
Код:
pdata.dat1 = eeprom_read_byte ((uint8_t *)pdata.adr1); // Считываем

eeprom_write_byte ((uint8_t *)pdata.adr1, pdata.dat1); // Записываем
Выходит операция взятия адреса была лишней и я все время получал указатель на указатель.

››Выходит операция взятия адреса была лишней
Нет, не лишняя.
Не буду утверждать на все 100% (на 99 можно):
Код:
pdata.dat1 = eeprom_read_byte ((uint8_t *)pdata.adr1); // Считываем

eeprom_write_byte ((uint8_t *)pdata.adr1, pdata.dat1); // Записываем
этот код по-моему чушь полная...
Код:
pdata.dat1 = eeprom_read_byte ((uint8_t *)pdata.adr1); // Считываем
Это как я понимаю, чтение байта pdata.dat1 по адресу равному &pdata.dat1 (такое может быть если в eeprom лежит копия ОЗУ и адреса совпадают). Это еще ладно, но вот это:
Код:
pdata.dat1 = eeprom_read_byte ((uint8_t *)pdata.adr1); // Считываем
вообще нечто. Функции eeprom_read_byte передаётся как адрес значение байта pdata.adr1 и pdata.adr1 им теперь уже инициализируется(генерато� � случайных чисел может быть?). Мне неизвестен диапазон значений pdata.adr1, но если предположить что 0-255, то pdata.adr1 инициализируется байтами из eeprom с адресами 0-255.

Не знаю точно как для WinAVR. поэтому приведу код для IAR:
Код:
struct dataexchange         // Описание структуры для передачи данных
{
  unsigned char cmd;         // Код команды, которую нужно выполнить.
  unsigned char adr1;        // Адрес, используется в некоторых командах (старший байт).
  unsigned char adr2;        // Адрес, используется в некоторых командах (младший байт).
  unsigned char dat1;        // Данные, относящиеся к команде (первый байт).
  unsigned char dat2;        // Данные, относящиеся к команде (второй байт).
};
__eeprom struct dataexchange pdata_EEPROMCopy;// копия в еепром
struct dataexchange pdata;// структура в ОЗУ

unsigned char ReadByteFromEEPROM(unsigned short addr);
void WriteByteToEEPROM(unsigned short addr, unsigned char new_byte);

// запись
WriteByteToEEPROM((unsigned short)&pdata_EEPROMCopy.adr1, pdata.adr1);
// чтение 
pdata.adr1=ReadByteFromEEPROM((unsigned short)&pdata_EEPROMCopy.adr1);
Для WinARV __eeprom нужно заменить соотв. атрибутом (__attribute__ ((section (".eeprom"))) вроде).
_Артём_ вне форума  
Сказали "Спасибо" _Артём_
warel (28.06.2019)
Непрочитано 14.11.2011, 02:57  
kison
Почётный гражданин KAZUS.RUN
 
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
kison на пути к лучшему
По умолчанию Re: Как получить адрес элемента структуры?

Сообщение от _Артём_ Посмотреть сообщение
Не буду утверждать на все 100% (на 99 можно):
Оказывается 1% это много...
Сообщение от _Артём_ Посмотреть сообщение
Код:
pdata.dat1 = eeprom_read_byte ((uint8_t *)pdata.adr1); // Считываем
Это как я понимаю, чтение байта pdata.dat1 по адресу равному &pdata.dat1 (такое может быть если в eeprom лежит копия ОЗУ и адреса совпадают).
Не путаем адреса с данными. Это чтение по адресу adr1 в переменную dat1. dat1 и adr1 это не одна и та же переменная.
Сообщение от _Артём_ Посмотреть сообщение
Это еще ладно, но вот это:
Код:
pdata.dat1 = eeprom_read_byte ((uint8_t *)pdata.adr1); // Считываем
вообще нечто. Функции eeprom_read_byte передаётся как адрес значение байта pdata.adr1 и pdata.adr1 им теперь уже инициализируется(генерато� � случайных чисел может быть?).
И опять.
Сообщение от _Артём_ Посмотреть сообщение
Мне неизвестен диапазон значений pdata.adr1, но если предположить что 0-255, то pdata.adr1 инициализируется байтами из eeprom с адресами 0-255.
Это секретный тип - uint8_t. И его диапазон тоже секретен.
Сообщение от _Артём_ Посмотреть сообщение
Не знаю точно как для WinAVR. поэтому приведу код для IAR:
А теперь представьте, что еепром содержит один сплошной массив. Имеется структура в ОЗУ, которой Вы зачем то копию в еепром создали. В этой структуре есть поле с адресом - фактически это индекс массива в еепром. И поле с данными которые нужно писать/читать в тот самый массив в еепром. И все встанет на свои места. Правда почему то окажется что 1% куда больше 99...
kison вне форума  
Сказали "Спасибо" kison
warel (28.06.2019)
Непрочитано 14.11.2011, 06:03  
nonamedov
Почётный гражданин KAZUS.RUN
 
Регистрация: 06.06.2008
Сообщений: 1,519
Сказал спасибо: 76
Сказали Спасибо 427 раз(а) в 365 сообщении(ях)
nonamedov на пути к лучшему
По умолчанию Re: Как получить адрес элемента структуры?

Смысла в копировании в ЕЕПРОМ нет, как Вы, вообще, сможете воспользоваться адресом указанным в структуре в ЕЕПРОМ?! Вам нужна структура в ОЗУ, которая хранила (упорядочивала) бы данные в ЕЕПРОМ.
Сообщение от _Артём_ Посмотреть сообщение
__eeprom struct dataexchange pdata_EEPROMCopy;// копия в еепром
struct dataexchange pdata;// структура в ОЗУ
nonamedov вне форума  
Сказали "Спасибо" nonamedov
warel (28.06.2019)
Непрочитано 14.11.2011, 10:23  
k0stya_
Временная регистрация
 
Регистрация: 23.09.2007
Адрес: Кривой Рог, Украина
Сообщений: 55
Сказал спасибо: 34
Сказали Спасибо 34 раз(а) в 20 сообщении(ях)
k0stya_ на пути к лучшему
По умолчанию Re: Как получить адрес элемента структуры?

Все таки я плохо искал в гугле...
Вот, может кому-то пригодиться

Tip on storing initial values in EEPROM
k0stya_ вне форума  
Сказали "Спасибо" k0stya_
warel (28.06.2019)
Непрочитано 14.11.2011, 23:07  
CodeNameHawk
Вид на жительство
 
Регистрация: 21.10.2009
Сообщений: 349
Сказал спасибо: 181
Сказали Спасибо 65 раз(а) в 57 сообщении(ях)
CodeNameHawk на пути к лучшему
По умолчанию Re: Как получить адрес элемента структуры?

Для структуры по идее должно подойти
void eeprom_write_block (const void *__src, void *__dst, size_t __n)
void eeprom_read_block (void *__dst, const void *__src, size_t __n)
CodeNameHawk вне форума  
Сказали "Спасибо" CodeNameHawk
warel (28.06.2019)
 
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как изменить адрес подпрограммы обработки прерывания? Godzilla82 Микроконтроллеры, АЦП, память и т.д 21 23.08.2010 09:52
Keil C51 как изменить адрес загрузки Kabron Микроконтроллеры, АЦП, память и т.д 4 09.10.2009 23:31
Как получить теоретические значения выходного напряжения на активной нагрузке dasco Электроника - это просто 7 16.12.2008 14:44
Как построить график, для нескольких значений элемента? DRFAUST Микроконтроллеры, АЦП, память и т.д 3 10.03.2008 17:48
как из USB получить 2UARTa? Doctor-Morro Микроконтроллеры, АЦП, память и т.д 8 29.03.2007 02:11


Часовой пояс GMT +4, время: 13:19.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.