Перейти к содержанию
    

Запись данных в EEPROM

Пытаюсь записать пару чисел в 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. В стандарный листинг программы дописал лишь описание функции. А в основном цикле - вызов функции с параметрами.

 

Подскажите, что делаю не так.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подскажите, что делаю не так.

В 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_;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну если хочется на "низком уровне":

// фича 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 тактов ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не понял, где у меня ошибка...

 

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

 

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

 

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

 

undefined symbol 'cli()'

this #pragma is not allowed here

Изменено пользователем Владимир_КПИ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не понял, где у меня ошибка...
Ошибка скорее всего была в отсутствии оптимизации.

мужду

EECR = (1<<EEMWE);

и

EECR = (1<<EEWE);

должно (в командах проца) пройти не более 4 тактов, читайте подробно даташит...

Ещё непонятно что означает "1<<EEWE" и "|="
Ну это Вам однозначно к K&R... (типа перечитываем учебник по С)

Подсказываю, EEWE это номер бита в регистре EECR, со вторым разберетесь по мере чтения

EECR |= (1<<EECR.2);
А вот это круто !!!

После прочтения K&R раскажите какой будет результат этой операции

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

"A |= B;" эквивалентно "A = A | B;"

А "1<<EEWE" – это сдвиг 1 влево EEWE число раз.

Тогда "EECR |= (1<<EEWE);" - эта команда устанавливает бит строба записи в регистре EECR.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

должно (в командах проца) пройти не более 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?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

То есть после установки бита 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 - это конечно одно и то же,

просто атмел в какой-то момент сменил имя и нужно свериться с инклудом на Ваш чип

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, хорошо расписали. Вроде понял.

 

Не думал, что так сложно будет записать что-то в 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 вроди бы многие пользуются.

 

Получилось! :)

 

 

Сделал так:

/* Write logical one to EEMWE */

EECR |= (1<<EEMWE);

/* Start eeprom write by setting EEWE */

#asm("sbi EECR,1");

 

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

 

Но всё равно вопрос остался актуальным - как сделать на С. Пример записи взят из документации. Должен работать же.

Изменено пользователем Владимир_КПИ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы точно уверены что в этом месте нужно оптимизацию выключать ?

И для чего ? Что бы между записью EEMWE и EEWE прошло > 4 тактов ?

Нет, это для того,чтобы компилятор первое присваивание не заоптимизировал до "совсэм нэт". От такой это странный продукт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет, это для того,чтобы компилятор первое присваивание не заоптимизировал до "совсэм нэт". От такой это странный продукт.
Тогда это очень странный продукт, EECR обязан быть объявлен как volatile.

 

 

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

Если все же хотите без включения оптимизации, тогда ВОЗМОЖНО так заработает:

unsigned char tmp1,tmp2;
.............
  tmp1 = EECR | (1<<EEMWE);
  tmp2 = EECR | (1<<EEWE);
  EECR = tmp1;
  EECR = tmp2;
............

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Последний вариант работает. Проверил самый первый вариант - тоже работает. Странно.

 

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

 

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

 

Насколько я понимаю, сразу же после прошития программы, МК начинает работать. То есть я его не отсоединял от программатора, а сразу же считал содержимое памяти.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

Данные могли остаться в EEPROM от предыдущего раза, если прошивался только Flash.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...