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

 
 
 
Reply to this topicStart new topic
> Переброс массива из 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
sKWO
сообщение Aug 23 2008, 07:32
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Покажите пожалста с каким квалификатором у Вас обьявлен массив
Цитата
win_ee


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
Sergey Reva
сообщение Aug 23 2008, 07:36
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 70
Регистрация: 22-04-07
Из: Poltava/Kharkov
Пользователь №: 27 243



Цитата(SZ0 @ Aug 23 2008, 10:22) *
А как его заставить увеличиваться на байт, не могу сообразить cranky.gif

unsigned short - 16 бит, поэтому на 2 байта увеличивается
Go to the top of the page
 
+Quote Post
SZ0
сообщение Aug 23 2008, 07:56
Сообщение #4


Местный
***

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



Цитата(Sergey Reva @ Aug 23 2008, 13:36) *
unsigned short - 16 бит, поэтому на 2 байта увеличивается


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

Цитата(sKWO @ Aug 23 2008, 13:32) *
Покажите пожалста с каким квалификатором у Вас обьявлен массив


В файле описание массивов
Прикрепленные файлы
Прикрепленный файл  array.txt ( 4.52 килобайт ) Кол-во скачиваний: 73
 
Go to the top of the page
 
+Quote Post
Sergey Reva
сообщение Aug 23 2008, 08:10
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 70
Регистрация: 22-04-07
Из: Poltava/Kharkov
Пользователь №: 27 243



Цитата(SZ0 @ Aug 23 2008, 10:56) *
Это я понимаю, но вроде как-то возможно заставить увеличиваться на байт.


..
unsigned char *ptr_win;
..
ptr_win = (unsigned char *)&win[0];
...

так годится?
Go to the top of the page
 
+Quote Post
SZ0
сообщение Aug 23 2008, 08:28
Сообщение #6


Местный
***

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



Цитата(Sergey Reva @ Aug 23 2008, 14:10) *
..
unsigned char *ptr_win;
..
ptr_win = (unsigned char *)&win[0];
...

так годится?


Верно! А я почему-то твёрдо cranky.gif думал что если так сделаю, для указателя будет использоваться один байт, что не позволит мне обращаться ко всему массиву. Поэтому этот вариант откинул, даже не подумав откомпилить проект sad.gif

А с привильной инициализацией EEAR так и не получается.

EEAR = *ptr_win_ee++; это оказалось не правильно, т.к. EEAR присвивается значение расположенное по адресу ptr_win_ee. (результат писания на не выспавшуюся голову a14.gif )

Сообщение отредактировал SZ0 - Aug 23 2008, 08:40
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Aug 23 2008, 08:39
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



[quote name='SZ0' date='Aug 23 2008, 11:22' post='458992']
В поиске был... не могу разобраться с указателями 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++;
}


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

Ва уже сказали что ptr_win_ee и ptr_win указатели на массив данных типа unsigned short - т.е. двухбайтных величин. Указатель в любом случае будет увеличиваться на 2.Хотите увеличиывть на 1 объявляйте массивы как unsigned char. Может быть Вам стоит возложить все обязанности по считыванию данных из еепром на компилятор и использовать например такое:

Код
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
//sizeof(win) возвратит размер массива в байтах

while(i < (size_w/2)) // size_w/2 - кол-во элементов в массиве
{
  *ptr_win++ = *ptr_win_ee++;
  i++;
}
Go to the top of the page
 
+Quote Post
Sergey Reva
сообщение Aug 23 2008, 09:05
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 70
Регистрация: 22-04-07
Из: Poltava/Kharkov
Пользователь №: 27 243



Автор, у вас иар? Не знаю тонкостей, но он вроде сам генерит код для доступа к переменным которые объявлены как __eeprom, вы же написали свою процедуру.. mempfis_ предложил использовать стандартные средства, но этот код вроде не сработает, потому что ptr_win_ee = (unsigned short *)&win_ee[0]; убивает(?) квалификатор __eeprom, да и при стандартном иаровском доступе, нету смысла использовать побайтное копирование, достаточно просто обращатся к елементам стуктуры, он (иар) сам добавит нужный код

например
Код
win[0].ADC_sensor[0].A1=2;

уже сразу запишет значение в eeprom
Go to the top of the page
 
+Quote Post
mempfis_
сообщение Aug 23 2008, 09:10
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Кстати да ведь можно использовать и запись вида:
Цитата
for(i=0;i < (size_w/2);i++) // size_w/2 - кол-во элементов в массиве
{
ram_massiv[i] = ee_massiv[i];
}


И IAR и CVAVR спокойно воспринимают такие записи и сами вставляют необходимые функции считывания данных их еепром smile.gif главное чтобы массивы были одинакового типа (char, int и т.д)
Go to the top of the page
 
+Quote Post
SZ0
сообщение Aug 23 2008, 09:23
Сообщение #10


Местный
***

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



Цитата(mempfis_ @ Aug 23 2008, 14:39) *
Может быть Вам стоит возложить все обязанности по считыванию данных из еепром на компилятор и использовать например такое:

Код
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
//sizeof(win) возвратит размер массива в байтах

while(i < (size_w/2)) // size_w/2 - кол-во элементов в массиве
{
   *ptr_win++ = *ptr_win_ee++;
   i++;
}
}


Забыл сказать что компилятор IAR.

Такую конструкцию я пытался применить, думая что IAR сообразит. Но он лишь "гоняет" так *ptr_win++ = *ptr_win_ee++ байты в RAM, что в принципе верно. Т.к. в указателях адрес. А то что один адрес на еепром указывает, IAR не телепат smile.gif

Применение while(i < (size_w/2)) в таком виде ведёт к лишним затратам, т.к. size_w/2 постоянно обрабатывается в цикле.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 23 2008, 09:26
Сообщение #11


Гуру
******

Группа: Модераторы
Сообщений: 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
mempfis_
сообщение Aug 23 2008, 09:50
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(SZ0 @ Aug 23 2008, 13:23) *
Забыл сказать что компилятор IAR.

Такую конструкцию я пытался применить, думая что IAR сообразит. Но он лишь "гоняет" так *ptr_win++ = *ptr_win_ee++ байты в RAM, что в принципе верно. Т.к. в указателях адрес. А то что один адрес на еепром указывает, IAR не телепат smile.gif

Применение while(i < (size_w/2)) в таком виде ведёт к лишним затратам, т.к. size_w/2 постоянно обрабатывается в цикле.

А если не делать приведение типов:
ptr_win = (unsigned short *)&win[0];
ptr_win_ee = (unsigned short *)&win_ee[0];


а просто написать:
Код
[b]
unsigned char *ptr_win;
unsigned char __eeprom *ptr_win_ee;
ptr_win  = &win[0];
ptr_win_ee = &win_ee[0];[/b]

unsihned char size = size_w/2; // чтобы не усложнять жизнь циклу;)

while(i <size) // size_w/2 - кол-во элементов в массиве
{
  *ptr_win++ = *ptr_win_ee++;
  i++;
}




Цитата(mempfis_ @ Aug 23 2008, 13:30) *
А если не делать приведение типов:
ptr_win = (unsigned short *)&win[0];
ptr_win_ee = (unsigned short *)&win_ee[0];


а просто написать:
Код
[b]
unsigned char *ptr_win;
unsigned char __eeprom *ptr_win_ee;
ptr_win  = &win[0];
ptr_win_ee = &win_ee[0];[/b]

unsihned char size = size_w/2; // чтобы не усложнять жизнь циклу;)

while(i <size) // size_w/2 - кол-во элементов в массиве
{
  *ptr_win++ = *ptr_win_ee++;
  i++;
}



проверил у себя в иаре - код работает smile.gif
Go to the top of the page
 
+Quote Post
SZ0
сообщение Aug 23 2008, 12:47
Сообщение #13


Местный
***

Группа: Участник
Сообщений: 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 Текстовая версия Сейчас: 20th July 2025 - 07:31
Рейтинг@Mail.ru


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