|
Запись,чтение EEPROM |
|
|
|
Jul 4 2006, 09:36
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(glebka @ Jul 4 2006, 13:27)  Делаю проект на MEGA 168, использюю ICC. Пишу 4 слова в EEPROM, читаю только последнее записанное.Пример взял из даташита.В чем может быть проблема. Без исходников сказать ничего нельзя! Здесь уже неоднократно поднималась тема EEPROM например http://electronix.ru/forum/index.php?showtopic=16140 (правда для IAR) но там есть исходники их можно адаптировтаь
|
|
|
|
|
Jul 4 2006, 10:02
|

Шаман
     
Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221

|
Похоже в Этом Код EEAR=Addr; может быть ошибка. EEAR обрабатывается как 16-битный регистр? И вообще, проинспектируйте полученный после компиляции ассемблерный листинг (если это возможно в данной среде).
|
|
|
|
|
Jul 4 2006, 10:33
|
Частый гость
 
Группа: Свой
Сообщений: 199
Регистрация: 22-06-05
Пользователь №: 6 217

|
Цитата(beer_warrior @ Jul 4 2006, 14:17)  А не может ли быть следующего: 1.Читаете по указателю с последнего места записи - те указатель не возвращается к началу? 2.Пишете все по одному адресу - указатель не сдвигался? Прописал в макро номера страниц и при записе, и при чтении просто читаю макро и использую EEPromWrite( EEPROM_SERID_BYTE0_ADDR,gSerialID[0]); Вопрос к IgorKossak если можно по поддробней про обработку адресса,как это сделать правильно.
|
|
|
|
|
Jul 5 2006, 07:12
|

Шаман
     
Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221

|
Цитата(glebka @ Jul 4 2006, 13:33)  ...Вопрос к IgorKossak если можно по поддробней про обработку адресса,как это сделать правильно. Имелось в виду следующее: поскольку доступ к 16-битным регистрам 8-битным ядром осуществляется за две команды, то имеет значение очерёдность такого доступа, а именно: - читать надо сначала младший, потом старший; - писать надо сначала старший, потом младший; - обращение должно быть ТОЛЬКО парным, т. е. не должно быть обращения к одной из двух половин без обращения ко второй. Подробнее в описании в главе "Accessing 16-bit Registers".
|
|
|
|
|
Jul 5 2006, 08:40
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(IgorKossak @ Jul 5 2006, 11:12)  Цитата(glebka @ Jul 4 2006, 13:33)  ...Вопрос к IgorKossak если можно по поддробней про обработку адресса,как это сделать правильно.
Имелось в виду следующее: поскольку доступ к 16-битным регистрам 8-битным ядром осуществляется за две команды, то имеет значение очерёдность такого доступа, а именно: - читать надо сначала младший, потом старший; - писать надо сначала старший, потом младший; - обращение должно быть ТОЛЬКО парным, т. е. не должно быть обращения к одной из двух половин без обращения ко второй. Подробнее в описании в главе "Accessing 16-bit Registers". Это относится только к регистрам которые могут железом поменяться (таймеры) для адреса eeprom это не действует можно в любом порядке читать и писать!
|
|
|
|
|
Jul 5 2006, 09:39
|

Шаман
     
Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221

|
Цитата(KRS @ Jul 5 2006, 11:40)  Цитата(IgorKossak @ Jul 5 2006, 11:12)  Цитата(glebka @ Jul 4 2006, 13:33)  ...Вопрос к IgorKossak если можно по поддробней про обработку адресса,как это сделать правильно.
Имелось в виду следующее: поскольку доступ к 16-битным регистрам 8-битным ядром осуществляется за две команды, то имеет значение очерёдность такого доступа, а именно: - читать надо сначала младший, потом старший; - писать надо сначала старший, потом младший; - обращение должно быть ТОЛЬКО парным, т. е. не должно быть обращения к одной из двух половин без обращения ко второй. Подробнее в описании в главе "Accessing 16-bit Registers". Это относится только к регистрам которые могут железом поменяться (таймеры) для адреса eeprom это не действует можно в любом порядке читать и писать! Согласен, здесь это не актуально, но чтобы не плодить правила и когда-нибудь не ошибиться в связи с этим, я бы следовал этому правилу всегда. Тем более, что это не накладно.
|
|
|
|
|
Jul 7 2006, 09:56
|
Участник

Группа: Новичок
Сообщений: 20
Регистрация: 1-09-05
Из: Рыбинск
Пользователь №: 8 130

|
Цитата(glebka @ Jul 5 2006, 13:03)  Уррра.заработалою.
Код
unsigned char EEPromRead( unsigned int Addr ) {
//Setup adress register EEAR=(Addr&0xFF); //start EEPOM read by writing EERE SetBit(EECR,0); //Return data from Data register return EEDR; }
void EEPromWrite( unsigned int Addr, unsigned char Val ) { macroGlobalIntDisable; EEAR = Addr; // Load address EEDR = Val; // Load data to be written //Set logical one to EEMPE SetBit(EECR,2); //Set logical one to EEPE SetBit(EECR,1); macroToggleWatchdog; while(EECR&(1<<EEPE)){}; macroGlobalIntEnable; return; } Я пишу на ассемблере, но дело не в этом. Я когда-то тоже писал в EEPROM несколько байт подряд, ждал предыдущей записи. Когда байтов было 2 - все ОК. Но когда стало 4 - не работало. Я долго парился пока не обнаружил, что просто повторно срабатывает прерывание (запись шла внутри прерывания) - слишком долго это все. Короче я сделал такую вещь - небольшая структура типа буфера, похожая на стек (но не совсем стек, скорее куча), состоит из тела, указателя, размера. Тело - содержит пакеты из трех байт, два байта адрес и один байт данные, размер тела = 3*N байт, где N-размер тела в пакетах; Указатель - 2 байта, содержат адрес вершины кучи; Размер - 1 байт, содержит количество положенных пакетов в кучу. Если =0 - куча пустая. Подпрограммы такие: ПОЛОЖИТЬ_В_КУЧУ и ОБСЛУЖИТЬ_КУЧУ. В начале программы кучу инициализировать - указатель на начало тела, размер=0. ПОЛОЖИТЬ_В_КУЧУ вызывается в любом месте программы, где надо записать в EEPROM очередное число. Берет адрес, данные, ложит в кучу по указателю, передвигает указатель на 3, увеличивает размер на 1. На время работы с кучей запретить прерывания. ОБСЛУЖИТЬ_КУЧУ вызывается сравнительно редко по прерыванию, проверяет размер кучи если =0 ничего не делает, иначе проверяет завершилась ли предыдущая запись в EEPROM, если нет - ничего не делает, если да - берет из кучи по указателю данные, адрес, направляет в регистры EEPROM, запускает запись, передвигает указатель на 3 обратно, уменьшает размер на 1. Все. Вот такая штука значительно облегчила мне жизнь
|
|
|
|
|
Jul 7 2006, 10:35
|
Частый гость
 
Группа: Свой
Сообщений: 75
Регистрация: 7-04-05
Из: Украина
Пользователь №: 3 948

|
Извиняюсь за оффтопик,но зачем такие сложности.... В ICC есть готовые функции (вернее макросы) EEPROM_READ() и EEPROM_WRITE() объявленные в eeprom.h, они сами занимаются опросом готовности EEPROM. В хелпе по ICC всё расписано. Вот пример из этого же хелпа: #pragma data:eeprom int foo = 0x1234; char table[] = { 0, 1, 2, 3, 4, 5 }; #pragma data:data ... int i; EEPROM_READ((int)&foo, i); // i now has 0x1234
--------------------
Метрология - наука о достаточной точности.
|
|
|
|
|
Jul 7 2006, 11:45
|
Участник

Группа: Новичок
Сообщений: 20
Регистрация: 1-09-05
Из: Рыбинск
Пользователь №: 8 130

|
Дело не просто в опросе готовности. Дело в том, что не надо ждать вхолостую готовность. Вы в программе фактически просто отправляете данные в EEPROM без ожидания готовности со скоростью программы хоть тридцать байт друг за дружкой без всяких ожиданий. А они уже "сами без вашего участия" своим чередом со скоростью EEPROM улетят. Если не устраивает куча (нельзя вдруг нарушать последовательность записи) - можно добавить еще один указатель и сделать полноценный буфер-очередь.
Сообщение отредактировал Crystaly - Jul 7 2006, 11:47
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|