реклама на сайте
подробности

 
 
> Кто использовал EEPROM AVR, подскажите что не так?
Sirko
сообщение Feb 5 2009, 15:01
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 245
Регистрация: 15-08-07
Пользователь №: 29 795



Не получается сохранить данные в EEPROM ATMega8515.

Упростил код до минимума

Код
[font="Courier New"]int main(void){
     u08 eeData = 0x22;
     u16 eeAddr = 20;
     while(EECR & _BV(EEWE));       //    Ждать завершения предыдущей записи
     EEAR = (eeAddr & 0x01ff);      //    Проинициализировать регистр адреса
     EEDR = eeData;
     EECR |= _BV(EEMWE);            //    Установить флаг EEMWE
     EECR |= _BV(EEWE);             //    Начать запись в EEPROM

     while(EECR & _BV(EEWE));       //    Ждать завершения предыдущей записи
//   EEAR = 0;                      //    Сбросить адрес EEPEROM в "0"

     while(EECR & _BV(EEWE));       //    Ждать завершения предыдущей записи
     EEAR = (eeAddr & 0x01ff);      //    Проинициализировать регистр адреса
     EECR |= _BV(EERE);             //    Выполнить чтение
     eeData = EEDR;

     while(EECR & _BV(EEWE));       //    Ждать завершения предыдущей записи
//   EEAR = 0;                      //    Сбросить адрес EEPEROM в "0"[/font]

и тем не менее на выходе 0xFF.
Потратил много времени на поиск причины, но где ошибка, так и не понял. unsure.gif
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Sirko
сообщение Feb 5 2009, 18:35
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 245
Регистрация: 15-08-07
Пользователь №: 29 795



Народ, Огромное Вам Спасибо.
Конечно же -O0 имело место быть.

Уже даже начал кусочек ASMa цитировать, как обратил внимание на "кучу, кучу всего".
Жалко времени, гадко, что у самого ума не хватило, но опыта нет, а опыт - сын ...

Включил оптимизацию, все заработало.
Не знаю, как дальше пойдет дело, но просьба, если не сложно, прокоментируйте фрагмент кода, с которого все началось.
Возможно есть откровенные бока.
На счет маски 0x01ff - это была последняя надежда, хоть и глупая (где-то увидел).

CODE
void
EEPROM_write(volatile u08 bankNumber, volatile void *data, volatile u08 length){
cli();
u16 address = 1 + bankNumber * length;
u16 endAddress = address + length;
u08* pointer = (u08*) data;
while(address < endAddress){
while(EECR & _BV(EEWE)); // Ждать завершения предыдущей записи
EEAR = address++; // Проинициализировать регистр адреса
EEDR = *(pointer++);
EECR |= _BV(EEMWE); // Установить флаг EEMWE
EECR |= _BV(EEWE); // Начать запись в EEPROM
}
while(EECR & _BV(EEWE)); // Ждать завершения предыдущей записи
EEAR = 0; // Сбросить адрес EEPEROM в "0"
sei();
}

void
EEPROM_read(volatile u08 bankNumber, volatile void *data, volatile u08 length){
cli();
u16 address = 1 + bankNumber * length;
u16 endAddress = address + length;
u08* pointer = (u08*) data;
while(address < endAddress){
while(EECR & _BV(EEWE)); // Ждать завершения предыдущей записи
EEAR = address++; // Проинициализировать регистр адреса
EECR |= _BV(EERE); // Выполнить чтение
*(pointer++) = EEDR;
}
while(EECR & _BV(EEWE)); // Ждать завершения предыдущей записи
EEAR = 0; // Сбросить адрес EEPEROM в "0"
sei();
}


Может подскажите, как написать Си код, что бы без оптимизации нормально компилился.

Еще раз всем огромное Спасибо.

Сообщение отредактировал rezident - Feb 5 2009, 20:05
Причина редактирования: Уменьшение видимого объема цитаты исходника.
Go to the top of the page
 
+Quote Post
777777
сообщение Feb 6 2009, 09:48
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(Sirko @ Feb 5 2009, 21:35) *
Может подскажите, как написать Си код, что бы без оптимизации нормально компилился.

Это еще что за глупости? Оптимизация - обязательная часть процесса компиляции, без нее получается код в 4...5 раз больше и, соответственно, медленнее. Вы тоже наслушались страшилок об ошибках оптимизации? Отключение оптимизации IMHO предназначено исключительно для того, чтобы в случае, если вам покажется что в оптимизации ошибка, вы могли ее отключить и убедиться, что на самом деле ошибка в вашем коде.

У меня для работы с EEPROM есть два файла - eerw.h и eerw.c, я их просто подключаю к проекту и пользуюсь их функциями. Для записи там используется кольцевой буфер - если запись уже идет, то данные помещаются в этот буфер, а по прерыванию по завершении предыдущего цикла записи выбираются из буфера и ставятся на запись.
В основной программе нужно только вызвать EEInit() в начале, там где программируются порты и пр.
CODE
//
// eerw.h
//

#define EE_SIZE 16 // размер кольцевого буфера для записи в EEPROM

typedef struct tagEEdata
{
uint8_t Adr;
uint8_t Data;
} CEEdata;

void EEinit();
uint8_t ReadEE(uint8_t adr);
uint16_t ReadEE2(uint8_t adr);
uint32_t ReadEE4(uint8_t adr);
void WriteEE(uint8_t data, uint8_t adr);
void WriteEE2(uint16_t data, uint8_t adr);
void WriteEE4(uint32_t data, uint8_t adr);
void WriteNextByte();

CODE
//
// eerw.c - функции для чтения/записи в EEPROM
//

#include <avr/io.h>
#include <avr/interrupt.h>
#include "eerw.h"

CEEdata EEdata[EE_SIZE]; // буфер данных для записи в EEPROM
CEEdata *pInPtr, *pOutPtr; // указатели для записи в EEPROM

/*
* работа с EEPROM
*/

void EEinit()
{
pInPtr = pOutPtr = EEdata;
}

uint8_t ReadEE(uint8_t adr)
{
while(EECR & _BV(EEWE))
{}
EEAR = adr;
EECR |= _BV(EERE);
return EEDR;
}

uint16_t ReadEE2(uint8_t adr)
{
uint16_t res1 = ReadEE(adr), res2 = ReadEE(adr+1);
return res1 | (res2<<8);
}

uint32_t ReadEE4(uint8_t adr)
{
uint32_t res1 = ReadEE2(adr), res2 = ReadEE2(adr+2);
return res1 | (res2<<16);
}

void WriteEE(uint8_t data, uint8_t adr)
{
pInPtr->Adr = adr;
pInPtr->Data = data;
if(++pInPtr == &EEdata[EE_SIZE])
pInPtr = EEdata;
cli();
if((EECR & _BV(EERIE)) == 0)
{
EECR |= _BV(EERIE);
WriteNextByte();
}
sei();
}

void WriteEE2(uint16_t data, uint8_t adr)
{
WriteEE(data, adr);
WriteEE((data&0xff00)>>8, adr+1);
}

void WriteEE4(uint32_t data, uint8_t adr)
{
WriteEE2(data, adr);
WriteEE2((data&0xffff0000)>>16, adr+2);
}

void WriteNextByte()
{
EEAR = pOutPtr->Adr;
EEDR = pOutPtr->Data;
if(++pOutPtr == &EEdata[EE_SIZE])
pOutPtr = EEdata;
cli();
EECR |= _BV(EEMWE);
EECR |= _BV(EEWE);
sei();
}

/*
* Обработчик прерывания от EEPROM
*/

ISR(EE_RDY_vect)
{
if(pOutPtr == pInPtr)
EECR &= ~_BV(EERIE);
else
WriteNextByte();
}
Причина редактирования: Уменьшение видимого размера цитируемых исходников.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 12th August 2025 - 12:36
Рейтинг@Mail.ru


Страница сгенерированна за 0.01382 секунд с 7
ELECTRONIX ©2004-2016