COKPOWEHEU писал(а):Правы, но зачем изобретать велосипед? Тем более что разработчики компилятора должны, по идее, лучше разбираться в особенностях контроллеров, чем любители.
Да какой там, помилуй бог, велосипед? Там все просто, как три копейки. Два служебных регистра и регистровая пара адреса. Любитель, если он хочет в этой сфере как-то расти, должен изучать матчасть. Я понимаю, что программирование на Си, особенно у новичков, вообще не способствует изучению особенностей применяемого МК - зачем? есть компилятор, он все знает. Прямо как фонвизинский Митрофанушка: "зачем знать географию, есть извозчик, он довезет".
COKPOWEHEU писал(а):Вон, гуру cvavr утверждает, что при тамошнем способе ячейка сначала проверяется, могут запрещаться прерывания, могут быть ассемблерные вставки и так далее. Кроме того, это более стандартизованный способ, а значит, лучше в плане читаемости.
Ну, наворотить можно много чего. Тем не менее, под спойлером я еще раз привожу Си-шные функции для чтения и записи байта из даташита на МК. Какая религия может запретить их применение? Не зная, какой МК использует тредстартер, привожу функции из даташита на "народную" ATmeg'у 8. Но не думаю, что для других МК эти функции будут отличаться. Естественно, что для использования этих функций надо файл-описатель МК подключать. Либо самому объяснить компилятору, что такое эти EEAR, EEDR и т.д.
Очевидно, что если автор использует прерывания, то в этих функциях перед началом циклов записи-чтения прерывания надо запрещать, а в конце функции - разрешать. Еще красивее - сначала проверить бит I регистра SREG, и если он установлен, то прерывания запрещать, в конце снова разрешать, а если бит сброшен, то ничего не делать с прерываниями.
Спойлер
Код: Выделить всё
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);
}
unsigned char EEPROM_read(unsigned int uiAddress)
{
/* Wait for completion of previous write */
while(EECR & (1<<EEWE))
;
/* Set up address register */
EEAR = uiAddress;
/* Start eeprom read by writing EERE */
EECR |= (1<<EERE);
/* Return data from data register */
return EEDR;
}
По-моему, у авторе проблемы не с доступом к EEPROM, а с алгоритмизированием вообще.
Вот, к примеру, делать вот так
kotriks писал(а):по окончанию памяти я вставил while(1); чтобы проц в ступор вставал

в общем случае неправильно. Не должен МК уходить в бесконечный цикл при невозможности записи в EEPROM. И вообще в любую память. А еще шире - при невозможности любого действия МК не должен "зависать".
Если запись дошла до конца EEPROM, очевидно, что надо начинать запись сначала. А если там настолько важные данные, которые нельзя потерять, значит, надо принимать меры к тому, чтобы такая ситуация в принципе не могла произойти.
kotriks писал(а):но как сделать указатель чтобы запись шла в пустую следующюю яйчейку, а не уже записанную??

Вам уже пример программы привели, но я просто продублирую саму идею.
По фиксированному адресу (например, 0х00) в EEPROM выделяете необходимое кол-во байт, в зависимости от объема EEPROM, в которых храните адрес первой свободной ячейки в EEPROM. После старта МК читаете содержимое ячеек, хранящих адрес свободной ячейки и вуаля, используете этот адрес в функциях чтения или записи. После каждой записи в EEPROM инкрементировать адрес и переписывать ячейки, хранящие адрес. Все. Если дошли до конца EEPROM, то следующий адрес вычисляется, как 0х00+количество ячеек, хранящих адрес.
Напишите свою функцию, производящую все эти действия, при этом для физических актов чтения-записи ваша функция должна пользоваться теми функциями, которые я показал выше.
Для корректной работы в исходном состоянии нужно создать и файл *.eep, в котором в адресных ячейках разместить первый свободный адрес и вместе с заливкой программы прошить и EEPROM.
А можно использовать на адрес, а смещение, это как удобней, для EEPROM особой разницы нет.
Задача-то элементарная.