реклама на сайте
подробности

 
 
> Переброс массива из EEPROM в RAM используя указатели
SZ0
сообщение Aug 23 2008, 07:22
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 326
Регистрация: 14-02-06
Пользователь №: 14 331



В поиске был... не могу разобраться с указателями wacko.gif

Есть массив в EEPROM, при запуске проца надо перебросить его в RAM. Написал такой код:

Код
unsigned short *ptr_win, *ptr_win_ee, *ptr_eeprom, g = 0;

ptr_win = (unsigned short *)&win[0];
ptr_win_ee = (unsigned short *)&win_ee[0];

unsigned short size_w = sizeof(win), i = 0; //size_w размер массива в eeprom

while(i < size_w)
{
  EEAR = g++;
  EECR |= (1<<EERE);
  *ptr_win++ = EEDR;
  i++;
}


Не получилось вместо g использовать указатель ptr_win_ee, который указывает на массив в eeprom и присваивать его значение EEAR. И при увеличении указателя *ptr_win++ он увеличивается на два байта, вместо 1. А как его заставить увеличиваться на байт, не могу сообразить cranky.gif
Выручайте, а то голова ваще гудит 07.gif

В таком виде из EEPROM читаются все байты из массива, но пишутся они в RAM через 1 байт. Использование g не правильно, т.к. g инициализировано на начало eeprom. Потому что я заранее знаю где начало массива. А правильно через указание EEAR = *ptr_win_ee++ не получается.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Сергей Борщ
сообщение Aug 23 2008, 09:26
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Начинать надо с того, что из EEPROM считывание идет побайтно. Значит ваши указатели должны быть указателями на байт. К слову, sizeof() также возвращает размер объекта в байтах. Поскольку исходный массив у вас в словах, надо воспользоваться явным приведением указателей:
Код
unsigned char *ptr_win, *ptr_win_ee, i;

ptr_win = (unsigned char *)win;    // указатель на массив тождественен указателю на его нулевой элемент,
                            // поэтому более короткая запись вместо &win[0]
ptr_win_ee = (unsigned char *)win_ee;

do
{
  EEAR = (unsigned int)(ptr_win_ee++);
  EECR |= (1<<EERE);
  *ptr_win++ = EEDR;
}
while(++i < sizeof(win));  // массив явно ненулевого размера, поэтому используем более эффективный цикл do {} while()
Если компилятор IAR, то все проще:
Код
unsigned char *ptr_win;
__eeprom unsigned char *ptr_win_ee;
unsigned char i = 0;

ptr_win = (unsigned char *)win;
ptr_win_ee = (__eeprom unsigned char *)win_ee;

do
{
  *ptr_win++ = *ptr_win_ee++;
}
while(++i < sizeof(win));

Цитата(SZ0 @ Aug 23 2008, 12:23) *
Т.к. в указателях адрес. А то что один адрес на еепром указывает, IAR не телепат smile.gif
К компилятору обычно должен быть прилажен программист, который четко скажет компилятору, что этот указатель на данные в eeprom smile.gif
Цитата(SZ0 @ Aug 23 2008, 12:23) *
Применение while(i < (size_w/2)) в таком виде ведёт к лишним затратам, т.к. size_w/2 постоянно обрабатывается в цикле.
Так выкиньте лишнюю переменную и используйте в цикле sizeof(win)/2, которое вычисляется на этапе компиляции. Хотя, если включена оптимизация, компилятор должен вынести деление на 2 из цикла даже если size_w передается как параметр в функцию.

А еще эффективнее перейти к циклу do {} while (--i):
Код
ptr_win = (unsigned char *)win;
ptr_win_ee = (__eeprom unsigned char *)win_ee;
unsigned char i = sizeof(win);

do
{
  *ptr_win++ = *ptr_win_ee++;
}
while(--i);
Еще одна уловка: если будете использовать цикл с поэлементным (не побайтным) копированием, то лучше вместо sizeof(win)/2 сразу писать sizeof(win)/sizeof(win[0]) - это позволит не менять исходник этого кода если вдруг придется изменить размер элемента массива.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
SZ0
сообщение Aug 23 2008, 12:47
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 326
Регистрация: 14-02-06
Пользователь №: 14 331



Цитата(Сергей Борщ @ Aug 23 2008, 15:26) *
Начинать надо с того, что из EEPROM считывание идет побайтно...


Спасибо за подробные разъяснения, всё работает. Только здесь __eeprom unsigned char пришлось поменять на unsigned char __eeprom иначе IAR выдаёт ошибку.

Сообщение отредактировал SZ0 - Aug 23 2008, 13:02
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 19:40
Рейтинг@Mail.ru


Страница сгенерированна за 0.01382 секунд с 7
ELECTRONIX ©2004-2016