Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Запись данных в EEPROM
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
Motion
Пытаюсь записать пару чисел в EEPROM МК ATmega16.

Взял стандартную функцию записи из документации:

void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
/* Wait for completion of previous write */
while(EECR & (1<<EEWE))
;
/* Set up address and data registers */
EEAR = uiAddress;
EEDR = ucData;
/* Write logical one to EEMWE */
EECR |= (1<<EEMWE);
/* Start eeprom write by setting EEWE */
EECR |= (1<<EEWE);
}


При компиляции выдаёт ошибки:

undefined symbol 'EEWE'
undefined symbol 'EEMWE'




Попробовал так:

void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
/* Wait for completion of previous write */
while(EECR & (1<<EECR.1))
;
/* Set up address and data registers */
EEAR = uiAddress;
EEDR = ucData;
/* Write logical one to EEMWE */
EECR |= (1<<EECR.2);
/* Start eeprom write by setting EEWE */
EECR |= (1<<EECR.1);
}

Ошибки не выдаёт, но ничего не пишет в EEPROM


В основном цикле программы пишу:

EEPROM_write(0x00,0x00);
EEPROM_write(0x01,0xAA);

Для написания программы использую CodeVisionAVR. В стандарный листинг программы дописал лишь описание функции. А в основном цикле - вызов функции с параметрами.

Подскажите, что делаю не так.
Qwertty
Цитата(Владимир_КПИ @ Feb 10 2008, 18:46) *
Подскажите, что делаю не так.

В CV достаточно просто объявить переменную:
Код
eeprom char beta;

Дальше с ней можно работать как с обычной переменной:
Код
beta = 0x4F;
x = beta;
beta++;


Ну если хочется на "низком уровне":
Код
#define EERE    0
#define EEWE    1
#define EEMWE   2

void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
unsigned char _sreg_;
/* Wait for completion of previous write */
while(EECR & (1<<EEWE));
_sreg_ = SREG;
cli();
/* Set up address and data registers */
EEAR = uiAddress;
EEDR = ucData;
// фича CV - отключение оптимизации
#pragma opt-
/* Write logical one to EEMWE */
EECR = (1<<EEMWE);
/* Start eeprom write by setting EEWE */
EECR = (1<<EEWE);
#pragma opt+
SREG = _sreg_;
}
singlskv
Цитата(Qwertty @ Feb 10 2008, 20:13) *
Ну если хочется на "низком уровне":
Код
// фича CV - отключение оптимизации
#pragma opt-
/* Write logical one to EEMWE */
EECR = (1<<EEMWE);
/* Start eeprom write by setting EEWE */
EECR = (1<<EEWE);
#pragma opt+
Вы точно уверены что в этом месте нужно оптимизацию выключать ?
И для чего ? Что бы между записью EEMWE и EEWE прошло > 4 тактов ?
Motion
Не понял, где у меня ошибка...

Ещё непонятно что означает "1<<EEWE" и "|="

И что значит на низком уровне? Думал ассемблере, но команды для С.

При компиляции вашего варианта программы на "низком уровне" выдаёт ошибки

undefined symbol 'cli()'
this #pragma is not allowed here
singlskv
Цитата(Владимир_КПИ @ Feb 10 2008, 21:50) *
Не понял, где у меня ошибка...
Ошибка скорее всего была в отсутствии оптимизации.
мужду
EECR = (1<<EEMWE);
и
EECR = (1<<EEWE);
должно (в командах проца) пройти не более 4 тактов, читайте подробно даташит...
Цитата
Ещё непонятно что означает "1<<EEWE" и "|="
Ну это Вам однозначно к K&R... (типа перечитываем учебник по С)
Подсказываю, EEWE это номер бита в регистре EECR, со вторым разберетесь по мере чтения
Цитата
EECR |= (1<<EECR.2);
А вот это круто !!!
После прочтения K&R раскажите какой будет результат этой операции
jasper
Цитата(Владимир_КПИ @ Feb 10 2008, 23:50) *
Ещё непонятно что означает "1<<EEWE" и "|="

"A |= B;" эквивалентно "A = A | B;"
А "1<<EEWE" – это сдвиг 1 влево EEWE число раз.
Тогда "EECR |= (1<<EEWE);" - эта команда устанавливает бит строба записи в регистре EECR.
Motion
Цитата
должно (в командах проца) пройти не более 4 тактов, читайте подробно даташит...

читал что-то такое...

Цитата
Ошибка скорее всего была в отсутствии оптимизации.

То есть после установки бита EEMPE менее чем за 4-е такта нужно установить EEWE? Но эти две команды стоят одна за другой.

Как включить оптимизацию?

Полистал справочник по С. Оказывается "|" означает логическое или. Со сдвигом тоже разобрался.

Разберём строку "EECR |= (1<<EEWE);"

1<<EEWE - сдвиг 1 влево EEWE раз. Какой единицы? А чему равно EEWE? Это значение бита EEWE регистра EECR? Ничего не понятно.


Вот что написано в книге по поводу сдвига. Пример:

x=7 00000111
x=x<<1 00001110

То есть сдвигаются все биты влево 1 раз. Тут для меня всё понятно.

Почему нельзя просто написать EECR.1=1?
singlskv
Цитата(Владимир_КПИ @ Feb 10 2008, 22:55) *
То есть после установки бита EEMPE менее чем за 4-е такта нужно установить EEWE? Но эти две команды стоят одна за другой.
Это в С они стоят рядом, что при этом будет при компиляции зависит
от выбранного уровня оптимизации, при отключенной, >4 тактов запросто.
Цитата
Как включить оптимизацию?
CV не знаю, исчите в меню или читайте хелп.
Цитата
1<<EEWE - сдвиг 1 влево EEWE раз. Какой единицы? А чему равно EEWE? Это значение бита EEWE регистра EECR? Ничего не понятно.
Вот что написано в книге по поводу сдвига. Пример:
x=7 00000111
x=x<<1 00001110

1<<X
пусть X=3, тогда
было 00000001 (1)
стало 00001000 (1<<3)

EEWE - номер бита в EECR который содержит соответствующий флаг.
должен быть описан в соответствующем include файле, типа так:
#define EEWE 1
те запись (1<<EEWE) <=> (1<<1) <=> 0b00000010
Цитата
Почему нельзя просто написать EECR.1=1?
можно, но не всегда, ищите в даташитах
упоминание Read-Modify-Write...
EECR |= (1<<EEWE) означает:
-прочитать регистр EECR
-загрузить в другой регистр константу (1<<EEWE)
-сделать OR между 2 регистрами
-записать результат в EECR

надеюсь теперь понятно откуда берутся >4 тактов между записями EEMWE EEWE

кстати у Вас похоже какие-то запутки с инклудами,
то у Вас EEMWE то EEMPE - это конечно одно и то же,
просто атмел в какой-то момент сменил имя и нужно свериться с инклудом на Ваш чип
Motion
Спасибо, хорошо расписали. Вроде понял.

Не думал, что так сложно будет записать что-то в EEPROM.

Значит вначале программы мне необходимо добавить 2 строчки для первой версии программы:
#define EEWE 1
#define EEMWE 2

И оптимизировать при компиляции.

То есть текст программы должен принять вид:
Цитата
#define EEWE 1
#define EEMWE 2


// Declare your global variables here


void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
/* Wait for completion of previous write */
while(EECR & (1<<EEWE))
;
/* Set up address and data registers */
EEAR = uiAddress;
EEDR = ucData;
/* Write logical one to EEMWE */
EECR |= (1<<EEMWE);
/* Start eeprom write by setting EEWE */
EECR |= (1<<EEWE);
}



А основной цикл:
Цитата
while (1)
{
// Place your code here
EEPROM_write(0x00,0x00);
EEPROM_write(0x01,0xAA);
};


При компиляции ошибок не выдаёт. Оптимизировать пока не нашёл как.

А вообще странно. Неужели никто ничего не пишет в EEPROM? CodeVisionAVR вроди бы многие пользуются.

Получилось! smile.gif


Сделал так:
Цитата
/* Write logical one to EEMWE */
EECR |= (1<<EEMWE);
/* Start eeprom write by setting EEWE */
#asm("sbi EECR,1");


Запустил в отладчике - записало 2 байта в EEPROM

Но всё равно вопрос остался актуальным - как сделать на С. Пример записи взят из документации. Должен работать же.
Qwertty
Цитата(singlskv @ Feb 10 2008, 20:51) *
Вы точно уверены что в этом месте нужно оптимизацию выключать ?
И для чего ? Что бы между записью EEMWE и EEWE прошло > 4 тактов ?

Нет, это для того,чтобы компилятор первое присваивание не заоптимизировал до "совсэм нэт". От такой это странный продукт.
singlskv
Цитата(Qwertty @ Feb 11 2008, 00:20) *
Нет, это для того,чтобы компилятор первое присваивание не заоптимизировал до "совсэм нэт". От такой это странный продукт.
Тогда это очень странный продукт, EECR обязан быть объявлен как volatile.


Цитата(Владимир_КПИ @ Feb 11 2008, 00:08) *
А вообще странно. Неужели никто ничего не пишет в EEPROM? CodeVisionAVR вроди бы многие пользуются.
ищите включение оптимизации...
Если все же хотите без включения оптимизации, тогда ВОЗМОЖНО так заработает:
Код
unsigned char tmp1,tmp2;
.............
  tmp1 = EECR | (1<<EEMWE);
  tmp2 = EECR | (1<<EEWE);
  EECR = tmp1;
  EECR = tmp2;
............
Motion
Последний вариант работает. Проверил самый первый вариант - тоже работает. Странно.

Проверял так:

"зашил программу" Ponyprog. И сразу же считал содержимое EEPROM. 2 байты были изменены.

Насколько я понимаю, сразу же после прошития программы, МК начинает работать. То есть я его не отсоединял от программатора, а сразу же считал содержимое памяти.
SergCom07
Цитата(Владимир_КПИ @ Feb 11 2008, 01:08) *
А вообще странно. Неужели никто ничего не пишет в EEPROM? CodeVisionAVR вроди бы многие пользуются.

Можно проверить генерируемый CV ассемблерный код (CV сохраняет его в файл с расширением asm), найти нужный фрагмент и посмотреть сколько команд и тактов между двумя записями бит.

Цитата(Владимир_КПИ @ Feb 11 2008, 02:28) *
"зашил программу" Ponyprog. И сразу же считал содержимое EEPROM. 2 байты были изменены.

Данные могли остаться в EEPROM от предыдущего раза, если прошивался только Flash.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.