Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: не пишится в EEPROM данные
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Sholkin
Здравствуйте. Первый раз на вашем форуме. На том где я обычно страшиваю не кто не ответил .Посоветовали к вам. Проблема вот какая.
(тему по ентому можно посмотреть сдесь http://www.fulcrum.ru/cgi-bin/bbs/mess_sel...564&page=1)
В процессоре не записываються данные в EEPROM. Написал программу в AVR 4.12 всё нормально данные пишуться прогу зашил в проц мега 8L на этом блоке где идет запись в EEPROM он застопориваеться и даль всё.
Вот мой кусок проги записи в эмуляторе всё тип топ
;запись расхода электроэнергии в EEPROM
clr r22 ;обнуление переменной условия записи в EEPROM
ldi r20,0
OUT $1E,R20
lds r21,$60
OUT $1D,R21
LDI R21,4
sts $3C,R21
LDI R21,2
sts $3C,R21
WEP0: SBIC $1C,1
RJMP WEP0

ldi r20,1
OUT $1E,R20
lds r21,$61
OUT $1D,R21
LDI R21,4
sts $3C,R21
LDI R21,2
sts $3C,R21
WEP1: SBIC $1C,1
RJMP WEP1

ldi r20,2
OUT $1E,R20
lds r21,$62
OUT $1D,R21
LDI R21,4
sts $3C,R21
LDI R21,2
sts $3C,R21
WEP2: SBIC $1C,1
RJMP WEP2

ldi r20,3
OUT $1E,R20
lds r21,$63
OUT $1D,R21
LDI R21,4
sts $3C,R21
LDI R21,2
sts $3C,R21
WEP3: SBIC $1C,1
RJMP WEP3

ldi r20,4
OUT $1E,R20
lds r21,$64
OUT $1D,R21
LDI R21,4
sts $3C,R21
LDI R21,2
sts $3C,R21
WEP4: SBIC $1C,1
RJMP WEP4

ldi r20,5
OUT $1E,R20
lds r21,$65
OUT $1D,R21
LDI R21,4
sts $3C,R21
LDI R21,2
sts $3C,R21
WEP5:SBIC $1C,1
RJMP WEP5

ldi r20,6
OUT $1E,R20
MOV r21,r15
OUT $1D,R21
LDI R21,4
sts $3C,R21
LDI R21,2
sts $3C,R21
WEP6:SBIC $1C,1
RJMP WEP6
;обнуление памяти о расходе електроэнергии
ldi r16,0b00000000 ;временно заносим данные о электроэнергии
sts $60,r16
sts $61,r16
sts $62,r16
sts $63,r16
sts $64,r16
sts $65,r16
clr r15
; чтение из EEPROM данных расхода электроэнергии в десятичной форме
; и запись их в память
ldi R20,0 ;чтение 1 цифры
OUT $1E,R20
LDI R20,1
OUT $1C,R20
REP0:SBIC $1C,0
RJMP REP0
IN R21,$1D
sts $60,r21

ldi R20,1 ;чтение 2 цифры
OUT $1E,R20
LDI R20,1
OUT $1C,R20
REP1:SBIC $1C,0
RJMP REP1
IN R21,$1D
sts $61,r21

ldi R20,2 ;чтение 3 цифры
OUT $1E,R20
LDI R20,1
OUT $1C,R20
REP2:SBIC $1C,0
RJMP REP2
IN R21,$1D
sts $62,r21

ldi R20,3 ;чтение 4 цифры
OUT $1E,R20
LDI R20,1
OUT $1C,R20
REP3:SBIC $1C,0
RJMP REP3
IN R21,$1D
sts $63,r21

ldi R20,4 ;чтение 5 цифры
OUT $1E,R20
LDI R20,1
OUT $1C,R20
REP4:SBIC $1C,0
RJMP REP4
IN R21,$1D
sts $64,r21

ldi R20,5 ;чтение 6 цифры
OUT $1E,R20
LDI R20,1
OUT $1C,R20
REP5:SBIC $1C,0
RJMP REP5
IN R21,$1D
sts $65,r21

ldi R20,6 ;чтение номера счётчика из EEPROM
OUT $1E,R20
LDI R20,1
OUT $1C,R20
REP6:SBIC $1C,0
RJMP REP6
IN R15,$1D ;запись номера счётчика в регистор

; конец чтение из EEPROM данных расхода электроэнергии в десятичной форме
Потом сделал как доке сначала команду WEP0: SBIC $1C,1
RJMP WEP0
потом OUT $1E,R20
lds r21,$60
OUT $1D,R21
LDI R21,4
sts $3C,R21
LDI R21,2
sts $3C,R21
думал в этом деле нет всё осталось по прежнему. чегодальше делать где рыть не знаю
Dima_Ag
ПОсмотрите в Datasheet на MEGA8 , на стр.20 и 21 приведён пример работы с ЕЕПРОМ.
Kuzmi4
2 Sholkin - вот, собсно всё работает и на 8-й и на 168-й и на 16-й..

--------------------------------------------------------------------------------------------------

void STORE_STRUCT_2_EEPROM(UINT E2P_addr, char *p2str, UINT length)
{
/////////////////
cli();

CRC4SEND.crcuint = MakeCRC16(&EEPROM_DATA,EEPROM_CONFIG_INFO_VOLUME);//crcuint
EEPROM_DATA.EEP_CRC16 = CRC4SEND.crcuint;
/////////////////
while (length--)
{

while(EECR & (1<<EEPE)) ;
/////////////////////////
EEAR = E2P_addr++;//location
EEDR = *p2str++;//byte
/* Write logical one to EEMPE */
EECR |= (1<<EEMPE);
/* Start eeprom write by setting EEPE */
EECR |= (1<<EEPE);
asm volatile ("nop");
asm volatile ("nop");


}
/////////////////
sei();
/////////////////
}
//*************************************************************
//*************************************************************
//*************************************************************
void GET_STRUCT_FROM_EEPROM(UINT E2P_addr, char *p2str, UINT length)
{
//////////////////////
cli();
//////////////////////
while (length--)
{
//cli();
//////////////////////
while(EECR & 0x02);//
//////////////////////
EEAR = E2P_addr++;//location;
EECR |= (1<<EERE); //
while ( CHECKBIT(EECR,0x01) ) ;//
*p2str++=EEDR;

}
//////////////////////
sei();
//////////////////////
}
//*************************************************************
Dopler
Не юбижайтесь, но довольно трудно разбираться в чужих листингах asm, если они такие большие и без всяких комментариев, так что не думаю, что кто-то этим займется. Также превожу свой код, копирующий массив данных в EEPROM.


Код
;----------------------------------------------------------------------------------------------------------------------------
; Загрузка параметров из EEPROM
LoadParameters:
    ldi    ZL,    0; Z указатель на начало области данных
    ldi    ZH,    0

    ldi    YL,    low(SpeedBuff)
    ldi    YH,    1; Работаем только в пределах первых 256 байт ОЗУ

    out     EEARH,     zero

EEPROM_read:    

    out     EEARL,     YL; Set up address (Y) in address register


    sbi     EECR,    EERE; Start eeprom read by writing EERE
    
    in     tmp,    EEDR; Read data from data register
    st    Y+,    tmp

    cpi    YL,    low(ParamsBuff+ParamsCount)
    brne    EEPROM_read

    ld    maxAdrH,    -Y
    ld    maxAdrL,    -Y

    ld    maxSpeed,    -Y
    ld    config,        -Y
    ld    tmp,        -Y
    mov    YL,        tmp
    
    ldi    sCountL,    1
    ldi    sCountH,    0

ret
;----------------------------------------------------------------------------------------------------------------------------



;----------------------------------------------------------------------------------------------------------------------------
; Сохранение параметров EEPROM
; Перед каждой запись байт проверяется на соответствие, запись производится только при обновлении значения
SaveParameters:
    ldi    YL,    low(SpeedBuff)
    out    EECR,    zero

; Wait for completion of previous write
EEPROM_Write:
    sbic     EECR,    EEPE
    rjmp     EEPROM_Write

; Set up address  in address register
    out     EEARL,     YL

; Start eeprom read by writing EERE
    sbi     EECR,    EERE
    
; Read data from data register
    in     tmp,    EEDR    ; сравниваем текущее значение с записанным
    ld    tmp2,    Y+
    
    cp    tmp,    tmp2
    breq    DoNotWrite    ; если это значение уже записано - выходим
    
; Write data  to data register
    out     EEDR,    tmp2    ; обновляем параметр
    
; Write logical one to EEMPE
    sbi     EECR,    EEMPE
    
; Start eeprom write by setting EEPE
    sbi     EECR,    EEPE

DoNotWrite:
    cpi        YL,        low(ParamsBuff+ParamsCount)
    brne    EEPROM_Write        

ret
sadat
Приведу и свой код:
A = R16 (привык называть регистры)

WRITE_EEPROM:
; записываем содержимое регистра А по установленному адресу в EEARH и ЕЕARL
wr_epr_1: sbic EECR, EEWE; ждем нуля
rjmp wr_epr_1;
out EEDR,a; данные на запись
sbi EECR, EEMWE; установили бит для подготовки записи
sbi EECR, EEWE; записываем байт
wr_epr_end: sbic EECR, EEWE; ждем пока запишется
rjmp wr_epr_end;
RET;

Все очень просто. Только нужно ждать (8мс на запись одного байта) и НЕ МЕНЯТЬ EEAR в процессе записи!!!!!
Sholkin
Здравствуйте
вроде в моём коде все коментарии прописаны програмка просто проверяеть записалось или нет.
Сделал я как в даташите (я и раньше писал что всё сотрел там и сделал так) оказалось при чтении у меня первое значение которое считываеться с еепрома не правильно считываеться вместо него считываеться последнне записаноое если продублировать с какй ячейки считываеться то всё в норме. При зашитии в проц даже байда что и была.
Вернулься к предыдущему варианту. В авеерке все как надо и пишиться и считываеться . Парни спасибо что привели свои програимки но они пахоже на мои но почему мой та не работает.
Чужое хорошо но своё та надо добить Что делать???7
bodja74
Цитата(Sholkin @ Apr 4 2007, 10:30) *
Чужое хорошо но своё та надо добить Что делать???7


Чужой код со своим сравнивать ,вот что делать.

ldi r20,0
OUT $1E,R20 <<В младший мы записали ,а где в старший ?
lds r21,$60
OUT $1D,R21
LDI R21,4
sts $3C,R21 <<К чему это шаманство ? Это же адресс таймера.
LDI R21,2
sts $3C,R21 << И это тоже?
WEP0: SBIC $1C,1
RJMP WEP0


Где установка EEMWE, EEWE ? В том же духе и по остальному коду.
В этом коде слишком много ошибок ,чтобы он работал даже на симуляторе smile.gif
Sholkin
bodja74 вы немного не правы . Симуляторе работает всё идеально и пишится всё как надо . Попробую применить код выше сказанный и посмотреть как он работает
mempfis_
Привет
вот ещё мой код который стопроцентно рабочий
(покрайней мере в мегеа8 и мега8535 работал)

; П/П чтения данных из EEPROM
; адрес ячейки памяти помещается в регистры s2:s1
; данные считываются из регистра s3
EEPROM_read: wdr
sbic EECR,EEWE
rjmp EEPROM_read
out EEARH,s2
out EEARL,s1
sbi EECR,EERE
in s3,EEDR
ret

; П/П записи данных в EEPROM
; адрес ячейки памяти помещается в регистры s2:s1
; данные помещаются в регистр s3
EEPROM_write:
wdr
sbic EECR,EEWE
rjmp EEPROM_write
out EEARH,s2
out EEARL,s1
out EEDR,s3
sbi EECR,EEMWE
sbi EECR,EEWE
ret
defunct
Sholkin
Цитата
...
OUT $1E,R20
lds r21,$61
...


Это просто дурной тон написания программ. В такой каше найти почему что-то не работает не тривиальная задача.

Для начала попробуйте использовать имена регистров, и разделите задачу на подзадачу - повыносите функции записи и чтения eeprom как тут уже советовали.
Sholkin
Здравствуйте
В пятницу поседел над програмкой вот чего получилось. Задачи у меня разделены сначала пишим в память потом в еепром потом обнуляем в памяти ячейки куда пишим считываем с еепром и записываем в память. Раньше у меня считывалось (убрал в програмке запись в еепром ) из еепром всё нормально как только занашу код записи прога не работаеть. Чего сделал в пятницу . Убрал все перечисленные ошибки зашил в память проца прогу (в имуляторе всё работает проверил) болт. Потом убрал опять записи в ячейки еепрома зашил всё считываеться . Потом вставил замись в еепром полько в первыю ячейку зашил заработало потом вставил запись во вторрую ячейку зашил работает теперь пишиться в две ячейки встави запиь в третью ячейку болт не стала работать прога. записи одинаковые но дальше 3 ячейки не пишит . Вообще не понял привожу новый код

Как он приведен пишится в ячейки еепрома в 0 и 1 если раблокировать запись в 3 прога на ней встанет колом пока мыслей нет в имуляторе всё окей
Пожскажите ещё чего может быть ? может проц гнилой ? или я ..................
rjmp reset
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
rjmp RXC
rjmp UDRE
rjmp TXC

aa: sbic $12,4 ; сравнение Pd(0)=1
rjmp outr0 ; пограмма передачи низкого уровня символа
rjmp outr1
outr0:cbi $12,4 ;вывод сигнала анти сброс (0)
rjmp aa
outr1:sbi $12,4 ;вывод сигнала анти сброс (1)
wdr ;сбрасывать WDT(вачдок таймер
rjmp aa
reset:
////////////////////////////////////////////////////////////////////////////////
ldi r16,0b00011001 ;установка защиты от зависания программы
out $21,r16
ldi r16,0b00000001 ;временно заносим данные о электроэнергии
sts $60,r16
ldi r16,0b00000010
sts $61,r16
ldi r16,0b00000011
sts $62,r16
ldi r16,0b00000100
sts $63,r16
ldi r16,0b00000101
sts $64,r16
ldi r16,0b00000110
sts $65,r16

ldi r16,0b10000001 ;временно заносим номер счётчика
mov r15,r16
ldi r16,$DF ;инициализация стека
out $3d,r16
clr r14
;запись расхода электроэнергии в EEPROM
WRITE_EEPROM:
clr r22 ;обнуление переменной условия записи в EEPROM
ldi r20,0
OUT $1F,R20
ldi r20,0
OUT $1E,R20
lds r21,$60
OUT $1D,R21
SBI $1C,2
SBI $1C,1
WEP0:SBIC $1C,1
RJMP WEP0


ldi r20,0
OUT $1F,R20
ldi r20,1
OUT $1E,R20
lds r21,$61
OUT $1D,R21
SBI $1C,2
SBI $1C,1
WEP1:SBIC $1C,1
RJMP WEP1

// ldi r20,0
// OUT $1F,R20
// ldi r20,2
// OUT $1E,R20
// lds r21,$62
// OUT $1D,R21
// SBI $1C,2
// SBI $1C,1
//WEP2:SBIC $1C,1
// RJMP WEP2

// ldi r20,0
// OUT $1F,R20
// ldi r20,3
// OUT $1E,R20
// lds r21,$63
// OUT $1D,R21
// SBI $1C,2
// SBI $1C,1
/////WEP3:SBIC $1C,1
// RJMP WEP3

// ldi r20,0
// OUT $1F,R20
// ldi r20,4
// OUT $1E,R20
// lds r21,$64
// OUT $1D,R21
// SBI $1C,2
// SBI $1C,1
//WEP4:SBIC $1C,1
// RJMP WEP4

// ldi r20,0
// OUT $1F,R20
// ldi r20,5
// OUT $1E,R20
// lds r21,$65
// OUT $1D,R21
// SBI $1C,2
// SBI $1C,1
//WEP5:SBIC $1C,1
// RJMP WEP5

// ldi r20,0
// OUT $1F,R20
// ldi r20,6
// OUT $1E,R20
// mov r21,r15
// OUT $1D,R21
// SBI $1C,2
// SBI $1C,1
//WEP6:SBIC $1C,1
// RJMP WEP6


;обнуление памяти о расходе електроэнергии
ldi r16,0b00000000 ;временно заносим данные о электроэнергии
sts $60,r16
sts $61,r16
sts $62,r16
sts $63,r16
sts $64,r16
sts $65,r16
clr r15

; чтение из EEPROM данных расхода электроэнергии в десятичной форме
; и запись их в память


ldi R20,0 ;чтение 1 цифры
OUT $1E,R20
SBI $1C,0
REP0:SBIC $1C,0
RJMP REP0
IN R21,$1D
sts $60,r21

ldi R20,1 ;чтение 2 цифры
OUT $1E,R20
SBI $1C,0
REP1:SBIC $1C,0
RJMP REP1
IN R21,$1D
sts $61,r21

ldi R20,2 ;чтение 3 цифры
OUT $1E,R20
SBI $1C,0
REP2:SBIC $1C,0
RJMP REP2
IN R21,$1D
sts $62,r21

ldi R20,3 ;чтение 4 цифры
OUT $1E,R20
SBI $1C,0
REP3:SBIC $1C,0
RJMP REP3
IN R21,$1D
sts $63,r21

ldi R20,4 ;чтение 5 цифры
OUT $1E,R20
SBI $1C,0
REP4:SBIC $1C,0
RJMP REP4
IN R21,$1D
sts $64,r21

ldi R20,5 ;чтение 6 цифры
OUT $1E,R20
SBI $1C,0
REP5:SBIC $1C,0
RJMP REP5
IN R21,$1D
sts $65,r21

ldi R20,6 ;чтение номера счётчика из EEPROM
OUT $1E,R20
SBI $1C,0
REP6:SBIC $1C,0
RJMP REP6
IN R15,$1D ;запись номера счётчика в регистор

; конец чтение из EEPROM данных расхода электроэнергии в десятичной форме

////////////////////////////////////////////////////////////////////////////
;установка режима порт D
ldi r16,0b11110010
ldi r17,0b00001101
out $11,r16 ;установка регистра DDR_D
out $12,r17 ;установка регистра PORT_D
;установка режима USART
ldi r23,0b00000010
out $0B,r23 ;установка регистра UCSRA
ldi r23,0b11011000 ;разрешаем работу приёмника/передатчика и разрешаем прерывания по завершению приёма/передачи
out $0A,r23 ;установка регистра UCSRB
ldi r23,0b00000000
out $20,r23 ;установка регистра UBRRH
ldi r23,0b10000110
out $20,r23 ;установка регистра UCSRC
ldi r23,0b01100111
out $09 ,r23 ;установка регистра скорости приёма/передачи UBRRL
sei ;разрешение прерывания
rjmp aa


RXC: sbi $12,5 ;вывод сигнала приём закончен
in r23,$0C ;получение данных с регистра USART
cpse r23,r15 ;сравнение данных регистра приёма USART с номером счётчика
rjmp felse ;не совпадение кода и на подпрограмму о передачи принятых данных
sbi $12,6 ;вывод сигнала о совподении кода
lds r23,$60 ;данные совпадают с номером счётчика
out $0C,r23
ldi r23,0b11111000
out $0A,r23 ; разрешаем прерывание по опусташению регистра данных USART
inc r14
reti
UDRE: mov r23,r14
cpi r23,0b00000001
brne writ3
lds r23,$61 ;передача второй цифры
out $0C,r23
inc r14
reti
writ3:cpi r23,0b00000010
brne writ4
lds r23,$62 ;передача третей цифры
out$0C,r23
inc r14
reti
writ4:cpi r23,0b00000011
brne writ5
lds r23,$63 ;передача четвёртой цифры
out $0C,r23
inc r14
reti
writ5:cpi r23,0b00000100
brne writ6
lds r23,$64 ;передача пятой цифры
out $0C,r23
inc r14
reti
writ6:lds r23,$65 ;передача шестой цифры
out $0C,r23
clr r14
ldi r23,0b11011000
out $0A,r23 ;заприщаем работу прерывания по опустошению регистра приёма/передачи
reti
TXC: sbi $12,7 ;вывод сигнала завершения передачи
reti

felse:mov r24,r23
out $0C,r24
ldi r24,0b10101010
out $0C,r24
reti
bodja74
1 Есть такая волшебная строчка
.include "C:\...\m8def.inc"
она позволит заместь адрессов регистров и битов писать их имена,и никто не будет высматривать названия регистров по вашим адрессам в коде.

2 Есть еще одна строчка
.org 0
И ваш код с векторами гарантировано начнется с 0

3 Если есть прерывания в момент записи в ЕЕПРОМ их нужно запрещать флагом I ,и разрешать после записи в ячейку

4 В прерываниях нужно сохранять регистр SREG при входе и востанавливать при выходе ,тоже самое и регистры РОН -если одни и теже используются в программе и прерываниях.

5. Уберите собаку ,если вы написали глючный код - она вам все равно не поможет, а только усложнит отладку.

Возможно я еще что нибудь подсказал если приведете код в читабельный вид (п 1) ,а так скорее всего можно предполагать что неприятности из за п3 и п4.
defunct
Цитата(bodja74 @ Apr 10 2007, 17:52) *
3 Если есть прерывания в момент записи в ЕЕПРОМ их нужно запрещать флагом I ,и разрешать после записи в ячейку

Ну тут надо немного уточнить.
Запрешать прерывания нужно обязательно перед записью EEMWE(EEMPE), а разрешать можно сразу после установки бита EEWE(EEPE) регистра EECR. Дожидаться окончания записи не обязательно, да и это довольно длительная операция - несколько ms. В примерах от атмела, проверка EEWE делается перед записью, а не после.
IgorKossak
Цитата(defunct @ Apr 11 2007, 00:20) *
... В примерах от атмела, проверка EEWE делается перед записью, а не после.

Перед чтением её тоже надо делать, т. к. в это время может осуществляться запись (если именно таким методом пользоваться).
Sholkin
Здравствуйте.
Зделал всё как мне сказали выше борада ещё больше запуталься какойто проклятый .
Если я делаю как у атмела (... В примерах от атмела, проверка EEWE делается перед записью, а не после) у мкня после записи в ЕЕпром читаем записываем в память в первую ячейку пишется значение не первой ячейки еепрома а последняя запись е еепром тесть пишу допустим в 6 ячеек еепрома обнуляю память потом считываю с еепропа пишу в память 6 ячейка еепрома пишится и в нулевую ячейку памяти и в шестую это всё в эмуляторе
Тот код который я превёл он в имуляторе работает без глюков вот потому так и оставил . Но я уже писал пишитчся полько первые две ячейки на третьеи прога встаёт колом .
Но вот породокс в коде при записи в третью ячеику функцию WEP0:SBIC $1C,1
RJMP WEP0
записал перед ldi r20,0
OUT $1F,R20
ldi r20,2
OUT $1E,R20
lds r21,$62
OUT $1D,R21
SBI $1C,2
SBI $1C,1
третья стала писаться проделал тоже с четвертой болт теперь на четвёртой клинит с ней ни так ни так не идёт перед записью ставил CLI запретить прерывание тоже болт
воопще мистика эта так пишится это так эта вообще не как
SOS .................................................
Sholkin
Парни что реально не кто не сможет помочь ?
Обидно
Wild007
Полностью согласен с:
Цитата(bodja74 @ Apr 10 2007, 18:52) *
1 Есть такая волшебная строчка
.include "C:\...\m8def.inc"
она позволит заместь адрессов регистров и битов писать их имена,и никто не будет высматривать названия регистров по вашим адрессам в коде.
..............................................
Возможно я еще что нибудь подсказал если приведете код в читабельный вид (п 1) ,......

А так разбирать wink.gif
Цитата
Это просто дурной тон написания программ. В такой каше найти почему что-то не работает не тривиальная задача
Sholkin
А если так уже программа написана вся . Ведь это только один блок её. Блок то прост запись в одну ячейку потом во вторую и так 7 раз потом считываем что не понятного в моём коде ? для профи по моему тут с первого взгляда видно.

Подумал попробую его упростить написать подпрограммой запись в ячейку не влоб как я написал может что и получиться попробую всётаки разобраться хотя ни чего не понятно. Почему по разному записываються данные
SasaVitebsk
Я вот смотрю, что здесь все по своей культурности человеческой, не могут вам напрямую сказать. Попробую я.

Вы для чего решили программированием занятся? Мне можете не отвечать, - себе ответьте.

Если вы хотите, хоть чего-то достичь и хоть в чём то разобраться, то не ленитесь. Я бы на вашем месте закатал бы рукава и переписал всё с нуля. Используя те советы, что Вам дали.

1) Оформить процедуру записи и процедуру чтения в подпрограммы.
2) Объявить мнемонические имена и использовать их
3) Максимально прокомментировать программу.


Боятся тут нечего. В результате текст вашей программы уменьшится примерно в пять раз!

И вам в ней будет удобно разбираться и нам.
Удачи.
Sholkin
Спасибо за оптвет Александр
Уже начал оформлять и запись и чтение процедурой думаю всё получиться . Напишу проверю результат на праздниках небыло времени.
ae_
Цитата(Sholkin @ May 2 2007, 16:17) *
Спасибо за оптвет Александр
Уже начал оформлять и запись и чтение процедурой думаю всё получиться . Напишу проверю результат на праздниках небыло времени.

Уважаемый Sholkin !
Начало обсуждения вашей программы в другой конференции: http://www.fulcrum.ru/cgi-bin/bbs/mess_sel...4592&page=1 датировано 21.06.2006, т.е. почти год назад. Ваш "проект" обсуждался под разными темами, но ответы на все ваши вопросы всегда сводились к просьбе привести программу в читабельный вид, используя мнемонические имена. Ваши ответы тоже всегда в стиле: "мне бы только ночь простоять, да день продержаться" - "вот допишу, отлажу, а потом всё переделаю, как вы советуете".
Если за прошедшие 10 месяцев вы так и не воспользовались советом десятков участников конференции, стоит ли удивляться, что по прежнему не находится желающих вам помогать?
KamikFROMrussia
Здорова всем!

Проблема с EEPROM:
Программирую для ATMEGA128 на С в AVRstudio 4.

#include <avr/io.h>

#define __nop __asm__ __volatile__ ("nop":smile.gif;

void eddyEEPROMwrite ( uint8_t ADDR, uint8_t DAT )
{
while(EECR & (1<<EEWE)) ;

EEAR = ADDR;//location
EEDR = DAT;//byte
/* Write logical one to EEMWE */
EECR |= (1<<EEMWE);
/* Start eeprom write by setting EEWE */
EECR |= (1<<EEWE);
__nop;
__nop;

}

uint8_t eddyEEPROMread ( uint8_t ADDR )
{

uint8_t getDAT;
while(EECR & 0x02);

EEAR = ADDR;//location;
EECR |= (1<<EERE);
while ( EECR & 0x01 );
getDAT=EEDR;
return getDAT;
}

int main(void)
{
uint8_t ad, da, res;
ad=0;
da=1;
eddyEEPROMwrite( ad, da );
res=eddyEEPROMread( ad );
while(1);
}

Кто-ниб может подсказать почему условие

while(EECR & 0x02);

не выполняется при том, что бит EEWE(0x02) в регистре EECR в нуле. Это первое.

Второй вопрос:

Кто-нибудь использовал стандартную библиотеку eeprom.h?
Зачем там нужен дефайн:
#define EEMEM __attribute__((section(".eeprom")))
и как его правильно использовать?

Приведите, пожалуйста, проверенные примеры на С записи данных в ЕЕПРОМ для атмеге128 или других схожих МК.

Заранее всем спасибо!
singlskv
Цитата(KamikFROMrussia @ May 7 2007, 01:07) *
int main(void)
{
uint8_t ad, da, res;
ad=0;
da=1;
eddyEEPROMwrite( ad, da );
res=eddyEEPROMread( ad );
while(1);
}

Во-первых, никогда не пишите в ячейку 0 EEPROM на AVR !!!
Код
Чтение:
      while(EECR & (1<<EEWE));  // запись закончена ?
      EEAR=EEAddr;                    // Адрес
      EECR |= (1<<EERE);          // читаем
      tmp=EEDR;                        // данные

Запись:
      while(EECR & (1<<EEWE));  // запись закончена ?
      EEAR=EEAddr;                    // Адрес
      EEDR=tmp;                        // данные
      EECR |= (1<<EEMWE);       // пишем
      EECR |= (1<<EEWE);
aesok
Цитата(KamikFROMrussia @ May 7 2007, 01:07) *
Кто-нибудь использовал стандартную библиотеку eeprom.h?
Зачем там нужен дефайн:
#define EEMEM __attribute__((section(".eeprom")))
и как его правильно использовать?


Так eeprom.h и нужно использовать, а не изобретать велосипед.

Проблема в этом коде:

EECR |= (1<<EEMWE);
/* Start eeprom write by setting EEWE */
EECR |= (1<<EEWE);

Бит EEWE должен быть установлен в единицу не позже чем через 4 цикла после установки в единицу бита EEMWE.

Во первых вы не отключаете прерывания, а оно спокойно может произойти между записью EEMWE и EEWE!

Во вторых язык С не дает ни каких гарантий о времени исполнения операций!!!! Да, на уровне оптимизации -Os этот код исполниться меньше чем за 4 цикла. Но без оптимизации (-O0) может быть больше 4 циклов.

Посмотрите ответ #5:
http://electronix.ru/forum/index.php?showtopic=29366

Там пример использования EEMEM и функций eeprom_write_block/eeprom_read_block. Также вы можете найти на своем диске файл 'avr-libc-user-manual.pdf' и посмотеть там описание функций eeprom_read_byte, eeprom_read_word, eeprom_write_byte и eeprom_write_word.

Анатолий.

PS: А вы знаете про вошебное слово: M103C?
defunct
Цитата(singlskv @ May 6 2007, 23:25) *
Во-первых, никогда не пишите в ячейку 0 EEPROM на AVR !!!

Что за предрассудки?
Sholkin
Здравствуйте.
ae_ вы немного не правы тогда у меня была в другом проблема и помощи я просил по USART.
Если прочитать у меня ни передовались данные в компр. Там мне отвичали не смотря на мой дурной тон написания . Проблема была в ни как написано а втом 1 была сосканирована документация с ошибко настройки USART были не правильно сделаны мне это указали сделал . Данные пошли но гонятся нули . Мне подсказали что нельзя сначала разряшить работу передатчика потом запретитьего разряшить работу приемника надо сразу разрешить и работу приёмника и передатчика я это сдела просто в силу своей неопытности не знал ни сталкивалься потом у меня не передовался данные первой ячейки с ошибками подсказали что нужно использовать внешний кварц а не внутрении так как у внутреннего частота ..... припоял внешний кварц всё стало работать идеально
Так что всё эти ошибки на тон написания не влияют даже если бы я написал как вы пишити (опыта у вас побольше намного) то толку бы не было . Этот блок программы я использовал чтобы смотреть что происходит с еепромом Я так написал чтобы разобраться с процом как что куда икак пишиться куда нолик куда единичка.
Это всё присказка к ae_ реально я от вас ни чего путного кроме ........
Может конечно я не прав новы профи вам видней а мы уш разьберёмся с USART. разобрался и ето добьём.


Теперь по делу с этим еепромом . Пошёл к человеку показал ему свой вот этот блок всё расписал. Вывод таков там всё правильно ошибок нет почему не пишиться пока трудно сказать. Он больше 2 ячеек еепрома не писал ку меня же надо записать 7 ячеек данных выше я уже описывал пишиться нулевая первая вторая на записи в третью встоёт прога колом.
Я написал в нормальном тоне как выше совет болт проблема скорей не в ентом ..... и мой тон написания опять не причём.
Попробую убрать USART из программы написать так если записалась зажечь стетодиот может в ентом проблема

для KamikFROMrussia сосвом уставом в чужой агород....... не похристиански создайте свою тему и тамм пи......
Извиняюсь за ранее
mdmitry
2KamikFROMrussia
В WINAVR есть библиотека для работы с eeprom, на форуме это уже обсуждалось.
IgorKossak
Цитата(defunct @ May 7 2007, 14:24) *
Что за предрассудки?

Да был когда-то давно такой глюк. Но его вроде бы исправили в последующих релизах МК, но неприятный осадок и привычка остались.
ae_
Цитата(Sholkin @ May 7 2007, 21:35) *
Теперь по делу с этим еепромом . Пошёл к человеку показал ему свой вот этот блок всё расписал. Вывод таков там всё правильно ошибок нет почему не пишиться пока трудно сказать.

Уважаемый Sholkin !
Потрудитесь заменить абсолютные адреса и номера битов на символьные имена регистров в/в и названий битов, прокомментировать каждую строчку, а также обяснить, что вы этими инструкциями пытаетесь сделать вот в этом крошечном фрагменте вашей программы:

ldi R20,0 ;чтение 1 цифры
OUT $1E,R20
SBI $1C,0
REP0:SBIC $1C,0
RJMP REP0
IN R21,$1D
sts $60,r21
Sholkin
Здравствуйте .
Код не могу привести вставляю тут нет такого шрифта кракозябы. Предоставлю попозже.
Дело втом что читается с еепром у меня нормально у меня не пишиться убрал подпрограмму передачи через USART/. Борода тоже самое в первые 0 в 1 в 2 ячейку пишиться когда пытаюсь записать в 4 ячейку все привет в пкрвее 3 все нормально.
ae_
Цитата(Sholkin @ May 10 2007, 15:09) *
Здравствуйте .
Код не могу привести вставляю тут нет такого шрифта кракозябы. Предоставлю попозже.

Хорошо, я сделаю этот фрагмент за вас, без применения шрифта "кракозябры":

.DSEG
Num1: .BYTE 1
.ESEG
EENum1: .DB 0
.CSEG
;...
LDI R20, LOW(EENum1)
OUT EEARL, R20
SBI EECR, EERE
REP0:
SBIC EECR, EERE
RJMP REP0
IN R21, EEDR
STS Num1,r21

По существу:
1. Перед изменением EEARL,EEARH надо проверять бит EEWE регистра EECR, так как в текущий момент может продолжаться запись в EEPROM
2. Проверка бита EERE, по вашему мнению, видимо должна помочь определить завершение чтения из EEPROM. Интересный способ, а datasheet читать пробовали? Как там рекомендуют определять окончание чтения из EEPROM, и нужно ли это делать?

И таких моментов в вашей программе - на каждом шагу. Если вы поменяете абсолютные адреса на символьные имена регистров и битов, то подобные ошибки в программе заметно даже при беглом взгляде. А разбираться в вашем текущем исходнике - мало желающих.
Sholkin
Здравствуйте .
Сейчас всё наладилось могу предоставить код
проивел в читабельный вид
Вот был такой

WRITE_EEPROM:
clr r22 ;обнуление переменной условия записи в EEPROM
ldi r20,0 ; заносим старший бит адреса EEPROM куда будем писать
OUT $1F,R20 ; заносим старший бит адреса EEPROM в 1F
ldi r20,0 ; заносим младшее значение адреса EEPROM куда будем писать
OUT $1E,R20 ; заносим младшее значение адреса EEPROM в $1E
lds r21,$60 ; заносим данные в регистр из памяти
OUT $1D,R21 ; заносим данные из регистра в EEPROM
SBI $1C,2 ; устанавливаем флаг EEWE разрешаем запись в EEPROM
SBI $1C,1 ; устанавливаем флаг EERE
WEP0:SBIC $1C,1 ; проверяем флаг записи в EEPROM
RJMP WEP0 ;
Расписал подробно в коментариях что этим хотел

Потом привёл в в такой вид

WEP3:SBIC EECR, EEWE ;проверяем флаг нет ли записи в EEPROM
RJMP WEP3

ldi VAR,0 ; заносим старший бит адреса EEPROM куда будем писать
OUT EEARH,VAR ; заносим старший бит адреса EEPROM в 1F
ldi VAR,3 ; заносим младшее значение адреса EEPROM куда будем писать
OUT EEARL,VAR ; заносим младшее значение адреса EEPROM в $1E
lds DATA,$63 ; заносим данные в регистр из памяти
OUT EEDR,DATA ; заносим данные из регистра в EEPROM
SBI EECR,EEMWE ; устанавливаем флаг EEWE разрешаем запись в EEPROM
SBI EECR,EEWE ; устанавливаем флаг EERE

Его я написал до сообщения AE . Были технические проблемы раньше не мог предоставить

По существу стал как в даташите снача проверять потом делать все изменения
Проблема осталась первые три ячейки пишет четвёртую болт. Некоторые говорят что
функцию

WEP3:SBIC EECR, EEWE ;проверяем флаг нет ли записи в EEPROM
RJMP WEP3
можно писать до изменя что и после изменения
Выше я как то писал что пробовал и так и так но если проверяю перед изменением в имуляторе нулевая ячейка памяти (когда считываю ) переписываеться на последнюю запись при записи в ЕЕПРОМ. Если проверяю у всех после изменения (код который первый в имуляторе всё окей) Но с этим как нибудь сам разберусь.
Проблема осталась почему боле трёх не пишит. У кого спрашивал те больше двух ячеек не писали сказать не могут смотрели всё правильно. Перед записью пробовал запрятить прерывания не помогло.
Воп в принципе и всё.
Кто чем может. С кодом AE по разбиралься не много его не понял
ae_
Цитата(Sholkin @ May 15 2007, 07:45) *
...
Проблема осталась почему боле трёх не пишит. У кого спрашивал те больше двух ячеек не писали сказать не могут смотрели всё правильно. Перед записью пробовал запрятить прерывания не помогло.
Воп в принципе и всё.
Кто чем может. С кодом AE по разбиралься не много его не понял

Уважаемый Sholkin !
Это не мой код, это ВАШ код (без изменений), который я привёл в читабельный вид, что бы его легче было понять мне, и, надеюсь, остальным тоже. Теперь вы сами не понимаете СВОЙ код в читабельном виде, круг замкнулся.

Вот, как написано вами:
ldi R20,0 ;чтение 1 цифры
OUT $1E,R20
SBI $1C,0
REP0:SBIC $1C,0
RJMP REP0
IN R21,$1D
sts $60,r21

Вот мой вариант:
.DSEG
Num1: .BYTE 1
.ESEG
EENum1: .DB 0
.CSEG
;...
LDI R20, LOW(EENum1)
OUT EEARL, R20
SBI EECR, EERE
REP0:
SBIC EECR, EERE
RJMP REP0
IN R21, EEDR
STS Num1,r21

Оба варианта одинаковы, но вариант с символьными именами позволяет легче обрнаружить ошибку: объясните, что делает инструкция "SBIC EECR, EERE" (SBIC $1C,0) ?
Sholkin
Здраствуйте.
То что это мой код я понял . Но почему вы указываете на ошибку в чтении . А у меня не идёт запись. (ошибку там я понял кажеться на которую вы указалино чтение у меня осуществляеться) я этот блок тоже убрал оставил только записать и зажечь диод.
ae_
Цитата(Sholkin @ May 16 2007, 12:14) *
Здраствуйте.
То что это мой код я понял . Но почему вы указываете на ошибку в чтении . А у меня не идёт запись. (ошибку там я понял кажеться на которую вы указалино чтение у меня осуществляеться) я этот блок тоже убрал оставил только записать и зажечь диод.

Этот фрагмент я привёл потому, что он просто бросился в глаза явной ошибкой, хотя вы утверждаете, что в программе ошибок нет (что ж тогда она не рабоет-то?!!!). И что бы найти остальные ошибки в вашей программе, которых там якобы нет, надо переписать исходник с использованием символьных имен регистров и битов, портов в/в, переменных в пямяти ит.д. Когда будет читабельный исходник, тогда любой участник конференции сможет легко ответить на все ваши вопросы.
Sholkin
Здравствуйте.
Вот этого фрагмента не достаточно

WEP3:SBIC EECR, EEWE ;проверяем флаг нет ли записи в EEPROM
RJMP WEP3

ldi VAR,0 ;заносим старший бит адреса EEPROM куда будем писать
OUT EEARH,VAR ; заносим старший бит адреса EEPROM в 1F
ldi VAR,3 ; заносим младшее значение адреса EEPROM куда будем писать
OUT EEARL,VAR ; заносим младшее значение адреса EEPROM в $1E
lds DATA,$60 ; заносим данные в регистр из памяти
OUT EEDR,DATA ; заносим данные из регистра в EEPROM
SBI EECR,EEMWE ; устанавливаем флаг EEWE разрешаем запись в EEPROM
SBI EECR,EEWE ; устанавливаем флаг EERE

Или привести весь код . Впринципе вот этот фрагмент в программе повторяеться 6 раз меняется только данные взятые из ячеек памяти
lds DATA,$60 ; заносим данные в регистр из памяти
это данные из ячеки памяти по адресу $60 пот тот же врагмент только из ячейки $61 $62 $63 ...
defunct
Цитата(Sholkin @ May 17 2007, 14:59) *
Вот этого фрагмента не достаточно


тут вроде бы все ок,
нехватает только cli/sei:

Код
OUT EEDR,DATA           ; заносим данные из регистра в EEPROM
cli
SBI EECR,EEMWE          ; устанавливаем флаг EEWE разрешаем запись в EEPROM
SBI EECR,EEWE             ; устанавливаем флаг EERE
sei


С записью вроде бы разобрались.
Если проблема осталась - ищите ее в чтении.
Еще, если вы оформите фрагметы записи и чтения ячейки eeprom как функции, то работать станет гораздо проще, и ошибок будет меньше.

Ниже я привожу пример записи/чтения массивов размером до 255 символов в/из eeprom. Разберитесь с этим примером.
Sholkin
Привет.
Привел все как надо на выходных (часть кода приводил)ещё хуже получилось третья ечейка заглохла и вообще не чего не пишиться. Вообще не понятно стало . Чем лучше делаешь тем хуже получаеться .
Чего надо ???????????????????????? Сегодня ещё по мучаюсь не получиться приведу весь код .
defunct
Цитата(Sholkin @ May 23 2007, 09:26) *
Чего надо ????????????????????????

Пожалуй тут осталось только
выпить йаду и разбить голову ап стену.

удачи
IgorKossak
Ну раз уж такое здесь началось, defunct получает предупреждение, а тема закрывается как исчерпавшая себя полностью.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.