Motion 0 10 февраля, 2008 Опубликовано 10 февраля, 2008 · Жалоба Пытаюсь записать пару чисел в 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 0 10 февраля, 2008 Опубликовано 10 февраля, 2008 · Жалоба Подскажите, что делаю не так. В 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 0 10 февраля, 2008 Опубликовано 10 февраля, 2008 · Жалоба Ну если хочется на "низком уровне": // фича 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 0 10 февраля, 2008 Опубликовано 10 февраля, 2008 (изменено) · Жалоба Не понял, где у меня ошибка... Ещё непонятно что означает "1<<EEWE" и "|=" И что значит на низком уровне? Думал ассемблере, но команды для С. При компиляции вашего варианта программы на "низком уровне" выдаёт ошибки undefined symbol 'cli()' this #pragma is not allowed here Изменено 10 февраля, 2008 пользователем Владимир_КПИ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 10 февраля, 2008 Опубликовано 10 февраля, 2008 · Жалоба Не понял, где у меня ошибка...Ошибка скорее всего была в отсутствии оптимизации. мужду EECR = (1<<EEMWE); и EECR = (1<<EEWE); должно (в командах проца) пройти не более 4 тактов, читайте подробно даташит... Ещё непонятно что означает "1<<EEWE" и "|="Ну это Вам однозначно к K&R... (типа перечитываем учебник по С) Подсказываю, EEWE это номер бита в регистре EECR, со вторым разберетесь по мере чтения EECR |= (1<<EECR.2);А вот это круто !!! После прочтения K&R раскажите какой будет результат этой операции Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jasper 0 10 февраля, 2008 Опубликовано 10 февраля, 2008 · Жалоба Ещё непонятно что означает "1<<EEWE" и "|=" "A |= B;" эквивалентно "A = A | B;" А "1<<EEWE" – это сдвиг 1 влево EEWE число раз. Тогда "EECR |= (1<<EEWE);" - эта команда устанавливает бит строба записи в регистре EECR. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Motion 0 10 февраля, 2008 Опубликовано 10 февраля, 2008 · Жалоба должно (в командах проца) пройти не более 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 0 10 февраля, 2008 Опубликовано 10 февраля, 2008 · Жалоба То есть после установки бита 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 0 10 февраля, 2008 Опубликовано 10 февраля, 2008 (изменено) · Жалоба Спасибо, хорошо расписали. Вроде понял. Не думал, что так сложно будет записать что-то в 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 Но всё равно вопрос остался актуальным - как сделать на С. Пример записи взят из документации. Должен работать же. Изменено 10 февраля, 2008 пользователем Владимир_КПИ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Qwertty 0 10 февраля, 2008 Опубликовано 10 февраля, 2008 · Жалоба Вы точно уверены что в этом месте нужно оптимизацию выключать ? И для чего ? Что бы между записью EEMWE и EEWE прошло > 4 тактов ? Нет, это для того,чтобы компилятор первое присваивание не заоптимизировал до "совсэм нэт". От такой это странный продукт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
singlskv 0 10 февраля, 2008 Опубликовано 10 февраля, 2008 · Жалоба Нет, это для того,чтобы компилятор первое присваивание не заоптимизировал до "совсэм нэт". От такой это странный продукт.Тогда это очень странный продукт, EECR обязан быть объявлен как volatile. А вообще странно. Неужели никто ничего не пишет в EEPROM? CodeVisionAVR вроди бы многие пользуются.ищите включение оптимизации... Если все же хотите без включения оптимизации, тогда ВОЗМОЖНО так заработает: unsigned char tmp1,tmp2; ............. tmp1 = EECR | (1<<EEMWE); tmp2 = EECR | (1<<EEWE); EECR = tmp1; EECR = tmp2; ............ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Motion 0 10 февраля, 2008 Опубликовано 10 февраля, 2008 · Жалоба Последний вариант работает. Проверил самый первый вариант - тоже работает. Странно. Проверял так: "зашил программу" Ponyprog. И сразу же считал содержимое EEPROM. 2 байты были изменены. Насколько я понимаю, сразу же после прошития программы, МК начинает работать. То есть я его не отсоединял от программатора, а сразу же считал содержимое памяти. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergCom07 0 13 февраля, 2008 Опубликовано 13 февраля, 2008 · Жалоба А вообще странно. Неужели никто ничего не пишет в EEPROM? CodeVisionAVR вроди бы многие пользуются. Можно проверить генерируемый CV ассемблерный код (CV сохраняет его в файл с расширением asm), найти нужный фрагмент и посмотреть сколько команд и тактов между двумя записями бит. "зашил программу" Ponyprog. И сразу же считал содержимое EEPROM. 2 байты были изменены. Данные могли остаться в EEPROM от предыдущего раза, если прошивался только Flash. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться