forum.mcontrollers.com - hlavní stránka forum.mcontrollers.com - fórum

 

.: fórum - hlavní stránka :.
Technology Stronghold by Rudolf Vesely
How to build Microsoft System Center hosted cloud series
FAQFAQ HledatHledat Seznam uživatelůSeznam uživatelů Uživatelské skupinyUživatelské skupiny RegistraceRegistrace
ProfilProfil StatistikaStatistika Soukromé zprávySoukromé zprávy PřihlášeníPřihlášení

 
Zápis a čtení na EEPROM ATmega32A

 
Přidat nové téma   Zaslat odpověď    Obsah fóra mcontrollers.com -> AVR
 
Kibirad
Anonymní





PříspěvekZaslal: 21 květen 2020, 5:52    Předmět: Zápis a čtení na EEPROM ATmega32A Citovat

Ahoj, obracím se na vás s otázkou ohledně zápisu a čtení z EEPROM. Potřebuji do ní na začátku programu uložit sekvenci čísel, kterou budu číst a případně dále upravovat při jeho běhu. Problém je, že se už druhý den pokouším najít nějaké informace ohledně nastavení EEARL a EEARH. Všude se odkazují na datasheet a ten jen říká, že se potřeba registry správně nastavit. Zkusil jsem snad vše možné a nemůžu se pohnout z místa. Do Atmel Studia jsem si překopíroval vzorový kód a pokoušel se mít odkazy na dvě rozdílné čtecí a zapisovací procedury pro vyloučení chyb. Vždy dojde k načtení z paměti poslední uložené hodnoty a nezáleží, že mám v každé zapisovací rutině jiné adresy. Už jsem naprostou zoufalý, protože nemůžu nikde nic najít. Velice bych ocenil osvětlení, případně nějakou pomoc. Díky
Návrat nahoru
 

 
Balů
Profesionál
Profesionál


Založen: 29.10.2012
Příspěvky: 795

PříspěvekZaslal: 21 květen 2020, 11:56    Předmět: Citovat

V datasheetu je to popsané jasně a srozumitelně. Dej sem kód a zkusíme najít chybu.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
Martin
ATmega pouzivatel
ATmega pouzivatel


Založen: 5.1.2008
Příspěvky: 1545

PříspěvekZaslal: 21 květen 2020, 15:17    Předmět: Citovat

úspešne používam niečo takéto (úryvok z rozsiahlejšieho cylu):

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


#define DATA_READ 0
#define DATA_WRITE 1
#define DATA_COMPARE 2


// praca s EEPROM
#define EEPROM_ADR_REGISTER EEAR
#define EEPROM_MAX_ADR E2END
#define EEPROM_DATA_REGISTER EEDR
#define EEPROM_POVOL_PRERUSENIE SET(EECR,EERIE)
#define EEPROM_ZAKAZ_PRERUSENIE RES(EECR,EERIE)

#define EEPROM_WR_BYTE SET(EECR,EEMWE); \
SET(EECR,EEWE)

#define EEPROM_RD_BYTE SET(EECR,EERE)
#define EEPROM_BUSY TST(EECR,EEWE)
#define EEPROM_MASKA_ERASE_WRITE (EECR &= 0x0f)

// DATA_READ, DATA_WRITE, DATA_COMPARE
uint8_t fn_int_rd_wr_eeprom(uint8_t prikaz, uint16_t *p_ciel, uint16_t index, uint8_t pocet)
{

volatile LOCAL uint16_t data_eep[DATA_EEP_MAX] EEMEM;

volatile LOCAL uint8_t beh_programu = FALSE;
uint16_t eep_number;
uint8_t *p_pointer_eep_eep, *p_pointer_eep_ram;


if (beh_programu == TRUE) return(FALSE);
if (index >= DATA_EEP_MAX) return(FALSE);
beh_programu = TRUE;


// ******************** SPRACOVANIE PAMATOVEJ OBLASTI **************************************
if ((index + pocet) >= DATA_EEP_MAX) {
pocet = (uint8_t)(DATA_EEP_MAX - index);
}
eep_number = 2 * pocet;
p_pointer_eep_eep = (uint8_t *)&data_eep[index];
p_pointer_eep_ram = (uint8_t *)p_ciel;

// ******************** SPRACOVANIE PRIKAZU **************************************
switch (prikaz) {

case DATA_READ : {
while (eep_number) {
// cakaj na pripadne uvolnenie prace s EEPROM
while(EEPROM_BUSY);
EEPROM_ADR_REGISTER = (uint16_t)p_pointer_eep_eep;
EEPROM_RD_BYTE;
*p_pointer_eep_ram = EEPROM_DATA_REGISTER;
p_pointer_eep_eep++;
p_pointer_eep_ram++;
eep_number--;
}
break;
}
case DATA_COMPARE : {
while (eep_number) {
// cakaj na pripadne uvolnenie prace s EEPROM
while(EEPROM_BUSY);
EEPROM_ADR_REGISTER = (uint16_t)p_pointer_eep_eep;
EEPROM_RD_BYTE;
if (*p_pointer_eep_ram != EEPROM_DATA_REGISTER) return(FALSE);
p_pointer_eep_eep++;
p_pointer_eep_ram++;
eep_number--;
}
break;
}
case DATA_WRITE : {
while (eep_number) {
while(EEPROM_BUSY);
EEPROM_ADR_REGISTER = (uint16_t)p_pointer_eep_eep;
EEPROM_DATA_REGISTER = (uint8_t)*p_pointer_eep_ram;
EEPROM_WR_BYTE;
p_pointer_eep_ram++;
p_pointer_eep_eep++;
eep_number--;
}
break;
}
}
beh_programu = FALSE;
return(TRUE);
}


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

v zásade je to okopčené z datasheetu a fungovalo to na prvý šum.
Pravdepodobne robíš nejakú elementárnu chybu. Ale to nie si sám Smile
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
Kibirad
Anonymní





PříspěvekZaslal: 21 květen 2020, 16:57    Předmět: Citovat

Asi jsem nezmínil, že pracuji v assembleru. Datasheet jsem pročetl několikrát a stejně mi není jasné to nastavení EEARL/H.
kód:

   .INCLUDE "m32Adef.inc"
   .org 0
   .def EEPROM = r16
   ldi r18,2
   ldi r20,4   
main:
   cpi r30,1
   breq EEPROM_WRITE
   cpi r30,2
   breq EEPROM_WRITE2
   cpi r30,3
   breq EEPROM_READ   
   cpi r30,4
   breq EEPROM_READ2
   rjmp main

EEPROM_WRITE:            
   SBIC EECR, EEWE         
   RJMP EEPROM_WRITE      

   LDI EEPROM,0x00
   OUT EEARH,EEPROM      
   LDI EEPROM,0x17
   OUT EEARL,EEPROM

   OUT EEDR, r18         
   SBI EECR, EEMWE         
   SBI EECR, EEWE         
   rjmp main

EEPROM_WRITE2:
   SBIC EECR, EEWE         
   RJMP EEPROM_WRITE2   

   LDI EEPROM,0x18
   OUT EEARL,EEPROM

   OUT EEDR, r20      
   SBI EECR, EEMWE         
   SBI EECR, EEWE         
   rjmp main            

EEPROM_READ:            
   SBIC EECR, EERE         
   RJMP EEPROM_READ       

   CLR EEPROM
   OUT EEARH, EEPROM
   LDI EEPROM, 0x17
   OUT EEARL, EEPROM

   SBI EECR,EERE         
   IN r19, EEDR         
   rjmp main

EEPROM_READ2:
   SBIC EECR, EERE         
   RJMP EEPROM_READ2       

   LDI EEPROM, 0x18
   OUT EEARL, EEPROM

   SBI EECR,EERE         
   IN r21, EEDR      
   rjmp main
Návrat nahoru
 

 
Martin
ATmega pouzivatel
ATmega pouzivatel


Založen: 5.1.2008
Příspěvky: 1545

PříspěvekZaslal: 21 květen 2020, 17:18    Předmět: Citovat

EEAR je adresný register. Dvojbajtový. Horný bajt je EEARH a dolný bajt je EEARL. Tam nie je čo špeci nastavovať.

Pre začiatok nastav EEARH = 0
A meň adresu iba v EEARL. Napríklad EEARL = 12.
Potom tam niečo zapíš, vypni zapni zaraidenie a to "niečo" načítaj.

Toť vsjo Smile
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
Martin
ATmega pouzivatel
ATmega pouzivatel


Založen: 5.1.2008
Příspěvky: 1545

PříspěvekZaslal: 21 květen 2020, 17:23    Předmět: Citovat

A netuším, či Ti to pomôže, ale ASM preklad toho môjho C-čka vyzerá nasledovne:


// DATA_READ, DATA_WRITE, DATA_COMPARE
uint8_t fn_int_rd_wr_eeprom(uint8_t prikaz, uint16_t *p_ciel, uint16_t index, uint8_t pocet)
{
2716: fb 01 movw r30, r22
volatile LOCAL uint8_t beh_programu = FALSE;
uint16_t eep_number;
uint8_t *p_pointer_eep_eep, *p_pointer_eep_ram;


if (beh_programu == TRUE) return(FALSE);
2718: 90 91 c4 01 lds r25, 0x01C4 ; 0x8001c4 <beh_programu.2465>
271c: 9f 3f cpi r25, 0xFF ; 255
271e: 09 f4 brne .+2 ; 0x2722 <fn_int_rd_wr_eeprom+0xc>
2720: 5a c0 rjmp .+180 ; 0x27d6 <fn_int_rd_wr_eeprom+0xc0>
if (index >= DATA_EEP_MAX) return(FALSE);
2722: 40 34 cpi r20, 0x40 ; 64
2724: 51 05 cpc r21, r1
2726: 08 f0 brcs .+2 ; 0x272a <fn_int_rd_wr_eeprom+0x14>
2728: 58 c0 rjmp .+176 ; 0x27da <fn_int_rd_wr_eeprom+0xc4>
beh_programu = TRUE;
272a: 9f ef ldi r25, 0xFF ; 255
272c: 90 93 c4 01 sts 0x01C4, r25 ; 0x8001c4 <beh_programu.2465>


// ******************** SPRACOVANIE PAMATOVEJ OBLASTI **************************************
if ((index + pocet) >= DATA_EEP_MAX) {
2730: ba 01 movw r22, r20
2732: 62 0f add r22, r18
2734: 71 1d adc r23, r1
2736: 60 34 cpi r22, 0x40 ; 64
2738: 71 05 cpc r23, r1
273a: 10 f0 brcs .+4 ; 0x2740 <fn_int_rd_wr_eeprom+0x2a>
pocet = (uint8_t)(DATA_EEP_MAX - index);
273c: 20 e4 ldi r18, 0x40 ; 64
273e: 24 1b sub r18, r20
}
eep_number = 2 * pocet;
2740: 30 e0 ldi r19, 0x00 ; 0
2742: 22 0f add r18, r18
2744: 33 1f adc r19, r19
p_pointer_eep_eep = (uint8_t *)&data_eep[index];
2746: 44 0f add r20, r20
2748: 55 1f adc r21, r21
274a: 40 50 subi r20, 0x00 ; 0
274c: 50 40 sbci r21, 0x00 ; 0
p_pointer_eep_ram = (uint8_t *)p_ciel;

// ******************** SPRACOVANIE PRIKAZU **************************************
switch (prikaz) {
274e: 81 30 cpi r24, 0x01 ; 1
2750: 39 f0 breq .+14 ; 0x2760 <fn_int_rd_wr_eeprom+0x4a>
2752: 50 f0 brcs .+20 ; 0x2768 <fn_int_rd_wr_eeprom+0x52>
2754: 82 30 cpi r24, 0x02 ; 2
2756: d9 f5 brne .+118 ; 0x27ce <fn_int_rd_wr_eeprom+0xb8>
eep_number--;
}
break;
}
case DATA_COMPARE : {
while (eep_number) {
2758: 21 15 cp r18, r1
275a: 31 05 cpc r19, r1
275c: b9 f4 brne .+46 ; 0x278c <fn_int_rd_wr_eeprom+0x76>
275e: 37 c0 rjmp .+110 ; 0x27ce <fn_int_rd_wr_eeprom+0xb8>
eep_number--;
}
break;
}
case DATA_WRITE : {
while (eep_number) {
2760: 21 15 cp r18, r1
2762: 31 05 cpc r19, r1
2764: 29 f5 brne .+74 ; 0x27b0 <fn_int_rd_wr_eeprom+0x9a>
2766: 33 c0 rjmp .+102 ; 0x27ce <fn_int_rd_wr_eeprom+0xb8>

// ******************** SPRACOVANIE PRIKAZU **************************************
switch (prikaz) {

case DATA_READ : {
while (eep_number) {
2768: 21 15 cp r18, r1
276a: 31 05 cpc r19, r1
276c: 81 f1 breq .+96 ; 0x27ce <fn_int_rd_wr_eeprom+0xb8>
276e: 24 0f add r18, r20
2770: 35 1f adc r19, r21
// cakaj na pripadne uvolnenie prace s EEPROM
while(EEPROM_BUSY);
2772: f9 99 sbic 0x1f, 1 ; 31
2774: fe cf rjmp .-4 ; 0x2772 <fn_int_rd_wr_eeprom+0x5c>
EEPROM_ADR_REGISTER = (uint16_t)p_pointer_eep_eep;
2776: 52 bd out 0x22, r21 ; 34
2778: 41 bd out 0x21, r20 ; 33
EEPROM_RD_BYTE;
277a: f8 9a sbi 0x1f, 0 ; 31
*p_pointer_eep_ram = EEPROM_DATA_REGISTER;
277c: 80 b5 in r24, 0x20 ; 32
277e: 81 93 st Z+, r24
p_pointer_eep_eep++;
2780: 4f 5f subi r20, 0xFF ; 255
2782: 5f 4f sbci r21, 0xFF ; 255

// ******************** SPRACOVANIE PRIKAZU **************************************
switch (prikaz) {

case DATA_READ : {
while (eep_number) {
2784: 42 17 cp r20, r18
2786: 53 07 cpc r21, r19
2788: a1 f7 brne .-24 ; 0x2772 <fn_int_rd_wr_eeprom+0x5c>
278a: 21 c0 rjmp .+66 ; 0x27ce <fn_int_rd_wr_eeprom+0xb8>
break;
}
case DATA_COMPARE : {
while (eep_number) {
// cakaj na pripadne uvolnenie prace s EEPROM
while(EEPROM_BUSY);
278c: 9f b3 in r25, 0x1f ; 31
278e: 89 2f mov r24, r25
2790: 82 70 andi r24, 0x02 ; 2
2792: 91 fd sbrc r25, 1
2794: fb cf rjmp .-10 ; 0x278c <fn_int_rd_wr_eeprom+0x76>
EEPROM_ADR_REGISTER = (uint16_t)p_pointer_eep_eep;
2796: 52 bd out 0x22, r21 ; 34
2798: 41 bd out 0x21, r20 ; 33
EEPROM_RD_BYTE;
279a: f8 9a sbi 0x1f, 0 ; 31
if (*p_pointer_eep_ram != EEPROM_DATA_REGISTER) return(FALSE);
279c: 61 91 ld r22, Z+
279e: 90 b5 in r25, 0x20 ; 32
27a0: 69 13 cpse r22, r25
27a2: 1c c0 rjmp .+56 ; 0x27dc <fn_int_rd_wr_eeprom+0xc6>
p_pointer_eep_eep++;
27a4: 4f 5f subi r20, 0xFF ; 255
27a6: 5f 4f sbci r21, 0xFF ; 255
p_pointer_eep_ram++;
eep_number--;
27a8: 21 50 subi r18, 0x01 ; 1
27aa: 31 09 sbc r19, r1
eep_number--;
}
break;
}
case DATA_COMPARE : {
while (eep_number) {
27ac: 79 f7 brne .-34 ; 0x278c <fn_int_rd_wr_eeprom+0x76>
27ae: 0f c0 rjmp .+30 ; 0x27ce <fn_int_rd_wr_eeprom+0xb8>
27b0: 24 0f add r18, r20
27b2: 35 1f adc r19, r21
}
break;
}
case DATA_WRITE : {
while (eep_number) {
while(EEPROM_BUSY);
27b4: f9 99 sbic 0x1f, 1 ; 31
27b6: fe cf rjmp .-4 ; 0x27b4 <fn_int_rd_wr_eeprom+0x9e>
EEPROM_ADR_REGISTER = (uint16_t)p_pointer_eep_eep;
27b8: 52 bd out 0x22, r21 ; 34
27ba: 41 bd out 0x21, r20 ; 33
EEPROM_DATA_REGISTER = (uint8_t)*p_pointer_eep_ram;
27bc: 81 91 ld r24, Z+
27be: 80 bd out 0x20, r24 ; 32
EEPROM_WR_BYTE;
27c0: fa 9a sbi 0x1f, 2 ; 31
27c2: f9 9a sbi 0x1f, 1 ; 31
p_pointer_eep_ram++;
p_pointer_eep_eep++;
27c4: 4f 5f subi r20, 0xFF ; 255
27c6: 5f 4f sbci r21, 0xFF ; 255
eep_number--;
}
break;
}
case DATA_WRITE : {
while (eep_number) {
27c8: 24 17 cp r18, r20
27ca: 35 07 cpc r19, r21
27cc: 99 f7 brne .-26 ; 0x27b4 <fn_int_rd_wr_eeprom+0x9e>
eep_number--;
}
break;
}
}
beh_programu = FALSE;
27ce: 10 92 c4 01 sts 0x01C4, r1 ; 0x8001c4 <beh_programu.2465>
return(TRUE);
27d2: 8f ef ldi r24, 0xFF ; 255
27d4: 08 95 ret
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
Kibirad
Anonymní





PříspěvekZaslal: 21 květen 2020, 17:49    Předmět: Citovat

Tak podle toho co jsi psal bych chápal, že mám ten kód co jsem poslal správně. EEARH nastavuji v prvním zápisu a čtení a pak již pracuji jen s EEARL. Pro první zápis a čtení je adresa 23 a pro druhé 24, takže to by mělo být také ok. Jenže když si kód otestuji v Atmel Studiu, tak mi vždy vypíše poslední zapsanou hodnotu - obě čtení mi vypíší poslední zapsanou hodnotu. Takže bych to chápal tak, že se první zadaná hodnota přepíše. Bohužel nemám přístup k HW a tak musím testovat pomocí debuggeru v Atmel Studiu.
Návrat nahoru
 

 
Martin
ATmega pouzivatel
ATmega pouzivatel


Založen: 5.1.2008
Příspěvky: 1545

PříspěvekZaslal: 21 květen 2020, 18:05    Předmět: Citovat

Ak to testuješ v simulátore, tak potom je to možno chyba v ňom. Na to by som sa nespoliehal. Pravdepodobne to máš správne a iba strácaš čas nekvalitným sw prostredím. Možno Smile
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
Kibirad
Anonymní





PříspěvekZaslal: 21 květen 2020, 18:14    Předmět: Citovat

To mě taky napadlo, ale sázel jsem spíš na to, že mám něco špatně.
Návrat nahoru
 

 
Balů
Profesionál
Profesionál


Založen: 29.10.2012
Příspěvky: 795

PříspěvekZaslal: 21 květen 2020, 18:36    Předmět: Citovat

Máš chybu ve čtecích rutinách. Na začátku máš SBIC EECR, EERE, ale v datasheetu je na začátku čtení SBIC EECR, EEWE. Bit pro start čtení se nuluje prakticky okamžitě, ale vždy (i před čtením) musíš kontrolovat, zda ještě neprobíhá zápis - tedy EEWE. Ve Tvém případě pořád ještě probíhá zápis, ale Ty už se snažíš číst.

Datasheet o čtení z EEPROM :
The user should poll the EEWE bit before starting the read operation. If a write operation is in
progress, it is neither possible to read the EEPROM, nor to change the EEAR Register.


Pro Martina (a nejenom pro něj) : Osobně nepoužívám čistě jenom zápis do EEPROM, ale vždy si před zápisem kontroluju, jestli je na dané adrese stejná hodnota a zapisuju až v případě neshody - v Cčku je to eeprom_update, v assembleru prostě vložím adresu do adresních registrů, přečtu a porovnám a zápis dávám až v případě neshody. Šetří se tím počet zápisů do EEPROM - a tedy EEPROMka, která má omezený počet zápisů, jako taková.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
Martin
ATmega pouzivatel
ATmega pouzivatel


Založen: 5.1.2008
Příspěvky: 1545

PříspěvekZaslal: 21 květen 2020, 19:20    Předmět: Citovat

No a je to, chyba sa našla Smile

osobne funkciu

fn_int_rd_wr_eeprom()

volám, len keď nastala nejaká zmena a ešte v odôvodnených prípadoch kontrolujem, či tá zmena neprichádza príliš často. Napríklad zápis nameraných minimálnych a maximálnych hodnôt.

Ak sa po inicializácii regulátora teploty mení teplota relatívne husto, program sa neplaší, ale po zápise do EEPROM ďalší zápis nenastane skôr ako napríklad za 10 skúnd. Maximálne hodnoty ostávajú medzitým v RAM. To, že sa jedná o zmenu ktorú treba zapísať nemusím zisťovať načítavaním z EEPROM, ale nastavením bitu už pri prvej zmene údajov v RAM želaným smerom. Potom stačí iba odpočítať čas od posledného zápisu do EEPROM, spraviť zápis a vynulovať príznak.

Ale o to sa stará úplne iná časť programu.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
 

 
Kibirad
Anonymní





PříspěvekZaslal: 21 květen 2020, 20:05    Předmět: Citovat

Neskutečně díky. Já se zaměřil na EEARL/H a a hledal v tom chybu. Hlavně jsem našel kód, který měl být na 100%, protože už byl odsouhlasený vyučujícím ale bohužel v něm byla tato chyba. Ještě jednou díky
Návrat nahoru
 

Zobrazit příspěvky z předchozích:   
Zobrazit předchozí téma :: Zobrazit následující téma  
Přidat nové téma   Zaslat odpověď    Obsah fóra mcontrollers.com -> AVR Časy uváděny v GMT + 2 hodiny
 
Strana 1 z 1
Přejdi na:  
Můžete přidat nové téma do tohoto fóra.
Můžete odpovídat na témata v tomto fóru.
Nemůžete upravovat své příspěvky v tomto fóru.
Nemůžete mazat své příspěvky v tomto fóru.
Nemůžete hlasovat v tomto fóru.
Můžete k příspěvkům připojovat soubory
Můžete stahovat a prohlížet přiložené soubory
 



Num Lock Holder - app to hold Numlock
Copyright © 2020 Rudolf Veselý, mcontrollers.com.
Je zakázáno používat části tohoto webu bez souhlasu autora. || Powered by phpBB © 2001, 2002 phpBB Group - with RedSquare DoubleJ(Jan Jaap)