|
|
  |
Переброс массива из EEPROM в RAM используя указатели |
|
|
|
Aug 23 2008, 07:22
|
Местный
  
Группа: Участник
Сообщений: 326
Регистрация: 14-02-06
Пользователь №: 14 331

|
В поиске был... не могу разобраться с указателями Есть массив в 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. А как его заставить увеличиваться на байт, не могу сообразить  Выручайте, а то голова ваще гудит В таком виде из EEPROM читаются все байты из массива, но пишутся они в RAM через 1 байт. Использование g не правильно, т.к. g инициализировано на начало eeprom. Потому что я заранее знаю где начало массива. А правильно через указание EEAR = *ptr_win_ee++ не получается.
|
|
|
|
|
Aug 23 2008, 07:32
|

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

|
Покажите пожалста с каким квалификатором у Вас обьявлен массив Цитата win_ee
--------------------
нельзя недооценивать предсказуемость глупости
|
|
|
|
|
Aug 23 2008, 07:36
|
Участник

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

|
Цитата(SZ0 @ Aug 23 2008, 10:22)  А как его заставить увеличиваться на байт, не могу сообразить  unsigned short - 16 бит, поэтому на 2 байта увеличивается
|
|
|
|
|
Aug 23 2008, 07:56
|
Местный
  
Группа: Участник
Сообщений: 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
|
|
|
|
|
Aug 23 2008, 08:10
|
Участник

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

|
Цитата(SZ0 @ Aug 23 2008, 10:56)  Это я понимаю, но вроде как-то возможно заставить увеличиваться на байт. .. unsigned char *ptr_win; .. ptr_win = (unsigned char *)&win[0]; ... так годится?
|
|
|
|
|
Aug 23 2008, 08:28
|
Местный
  
Группа: Участник
Сообщений: 326
Регистрация: 14-02-06
Пользователь №: 14 331

|
Цитата(Sergey Reva @ Aug 23 2008, 14:10)  .. unsigned char *ptr_win; .. ptr_win = (unsigned char *)&win[0]; ...
так годится? Верно! А я почему-то твёрдо  думал что если так сделаю, для указателя будет использоваться один байт, что не позволит мне обращаться ко всему массиву. Поэтому этот вариант откинул, даже не подумав откомпилить проект  А с привильной инициализацией EEAR так и не получается. EEAR = *ptr_win_ee++; это оказалось не правильно, т.к. EEAR присвивается значение расположенное по адресу ptr_win_ee. (результат писания на не выспавшуюся голову  )
Сообщение отредактировал SZ0 - Aug 23 2008, 08:40
|
|
|
|
|
Aug 23 2008, 08:39
|

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

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

Группа: Участник
Сообщений: 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
|
|
|
|
|
Aug 23 2008, 09:23
|
Местный
  
Группа: Участник
Сообщений: 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 не телепат  Применение while(i < (size_w/2)) в таком виде ведёт к лишним затратам, т.к. size_w/2 постоянно обрабатывается в цикле.
|
|
|
|
|
Aug 23 2008, 09:26
|

Гуру
     
Группа: Модераторы
Сообщений: 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 не телепат  К компилятору обычно должен быть прил ажен программист, который четко скажет компилятору, что этот указатель на данные в eeprom  Цитата(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)
|
|
|
|
|
Aug 23 2008, 09:50
|

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

|
Цитата(SZ0 @ Aug 23 2008, 13:23)  Забыл сказать что компилятор IAR. Такую конструкцию я пытался применить, думая что IAR сообразит. Но он лишь "гоняет" так *ptr_win++ = *ptr_win_ee++ байты в RAM, что в принципе верно. Т.к. в указателях адрес. А то что один адрес на еепром указывает, IAR не телепат  Применение 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++; } проверил у себя в иаре - код работает
|
|
|
|
|
Aug 23 2008, 12:47
|
Местный
  
Группа: Участник
Сообщений: 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
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|