| Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
Как получить адрес элемента структуры?
13.11.2011, 00:13
|
|
|
Временная регистрация
Регистрация: 23.09.2007
Адрес: Кривой Рог, Украина
Сообщений: 55
Сказал спасибо: 34
Сказали Спасибо 34 раз(а) в 20 сообщении(ях)
|
Как получить адрес элемента структуры?
Пишу программу на Си (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_
|
|
|
13.11.2011, 01:09
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
|
Re: Как получить адрес элемента структуры?
&pdata.adr1 - правильный способ. Дает указатель на элемент структуры.
Вам надо с записью разобраться. Ответить себе на пару вопросов - например что такое adr1. Скорее всего ответ будет - адрес куда писать в еепром. По сути - указатель. Так наверно и надо передавать не указатель на указатель, а само значение.
eeprom_write_byte ((void*)pdata.adr1, pdata.dat1); // Записываем
Возможно я конечно не понял цель. Что хотим получить то?
|
|
|
|
Эти 2 пользователя(ей) сказали Спасибо kison за это сообщение:
|
|
|
13.11.2011, 01:44
|
|
|
Заблокирован
Регистрация: 27.03.2007
Сообщений: 1,327
Сказал спасибо: 12
Сказали Спасибо 576 раз(а) в 460 сообщении(ях)
|
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.
|
|
|
|
Эти 2 пользователя(ей) сказали Спасибо Yurkin2007 за это сообщение:
|
|
|
13.11.2011, 11:39
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 06.06.2008
Сообщений: 1,519
Сказал спасибо: 76
Сказали Спасибо 427 раз(а) в 365 сообщении(ях)
|
Re: Как получить адрес элемента структуры?
Думаю, проблема в приоритете операций, приоритет операции взятие ссылки & ниже чем операции обращения к полю ., поэтому надо писать так: (&pdata).adr1.
|
|
|
|
Сказали "Спасибо" nonamedov
|
|
|
13.11.2011, 11:46
|
|
|
Временная регистрация
Регистрация: 23.09.2007
Адрес: Кривой Рог, Украина
Сообщений: 55
Сказал спасибо: 34
Сказали Спасибо 34 раз(а) в 20 сообщении(ях)
|
Re: Как получить адрес элемента структуры?
Фух, разобрался.
Спасибо Yurkin2007 и kison за помощь.
Все заработало в таком вот виде:
|
Код:
|
pdata.dat1 = eeprom_read_byte ((uint8_t *)pdata.adr1); // Считываем
eeprom_write_byte ((uint8_t *)pdata.adr1, pdata.dat1); // Записываем |
Выходит операция взятия адреса была лишней и я все время получал указатель на указатель.
|
|
|
|
Сказали "Спасибо" k0stya_
|
|
|
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"))) вроде).
|
|
|
|
Сказали "Спасибо" _Артём_
|
|
|
14.11.2011, 02:57
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 13.12.2004
Сообщений: 3,168
Сказал спасибо: 11
Сказали Спасибо 691 раз(а) в 503 сообщении(ях)
|
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...
|
|
|
|
14.11.2011, 06:03
|
|
|
Почётный гражданин KAZUS.RUN
Регистрация: 06.06.2008
Сообщений: 1,519
Сказал спасибо: 76
Сказали Спасибо 427 раз(а) в 365 сообщении(ях)
|
Re: Как получить адрес элемента структуры?
Смысла в копировании в ЕЕПРОМ нет, как Вы, вообще, сможете воспользоваться адресом указанным в структуре в ЕЕПРОМ?! Вам нужна структура в ОЗУ, которая хранила (упорядочивала) бы данные в ЕЕПРОМ.
Сообщение от _Артём_
|
__eeprom struct dataexchange pdata_EEPROMCopy;// копия в еепром
struct dataexchange pdata;// структура в ОЗУ
|
|
|
|
|
Сказали "Спасибо" nonamedov
|
|
|
14.11.2011, 10:23
|
|
|
Временная регистрация
Регистрация: 23.09.2007
Адрес: Кривой Рог, Украина
Сообщений: 55
Сказал спасибо: 34
Сказали Спасибо 34 раз(а) в 20 сообщении(ях)
|
Re: Как получить адрес элемента структуры?
Все таки я плохо искал в гугле...
Вот, может кому-то пригодиться
Tip on storing initial values in EEPROM
|
|
|
|
Сказали "Спасибо" k0stya_
|
|
|
14.11.2011, 23:07
|
|
|
Вид на жительство
Регистрация: 21.10.2009
Сообщений: 349
Сказал спасибо: 181
Сказали Спасибо 65 раз(а) в 57 сообщении(ях)
|
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
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 13:19.
|
|