Komunikace s EEPROM 24LC16B přes I2C(TWI) ATmega8 ASM

Zdravím,
dělám přístroj s LCD displejem řízený MCU ATmega8. Bohužel jsem zjistil že se mi celý program nevejde do programové paměti z důvodu že asi 1KB který ještě potřebuju, zabírají znakové řetězce které se vypisují na onen displej. Proto jsem se rozhodl použít I2C EEPROM 24LC16B, z důvodu že při návrhu řídící desky, jsem myslel doředu a vyvedl si TWI a USART na konektory, což se mi teď hodí. Přes PonyProg jsem do paměti natáhl HEX soubor s znakama, takže řeším jen čtení.
Bohužel s TWI i s EEPROM dělám poprvé, což vede k tomu že pokud něco nejde tak nevím jestli mám chybu v programu nebo v komunikaci.

Pro úplnost control byte (slave adresa) vypadá takto:

1|0|1|0|B2|B1|B0|R/W, kde B0 až B2 je adresa stránky.
(Organizace 8x256B = 2KB = 16Kbit) - tak jsem to pochopil ze sheetu.

Protože mám k dispozici LCD displej, zobrazuju na něm stavové kódy z registru TWSR. Dále mám k dispozici knížku od Davida Matouška - Práce s mikrokontroléry Atmel AVR ATmega16 se kterou jsem se v programu dopracoval do toho stavu:

Odešlu start bit, vrácen kód 0x08 - OK;
Odešlu slave adresu 0b10100000 - vrácen kód 0x18 - OK;
Odešlu offset 0b00000000 - vrácen kód 0x28 - OK;
Odešlu start bit, vrácen kód 0x10 - KO;
Odešlu slave adresu 0b10100001 - vrácen kód 0x40; - nevím jestli dobře nebo špatně

Nyní předpokládám že mi EEPROM začne valit data bajt po bajtu dokud nevgeneruji stopbit.

Dále jsem postupoval tak že jsem vynuloval TWINT čekal na nastaveni (cekani na prijem), přečetl TWDR, uložil si přijatou hodontu takto to udělal 16x v cyklu a poté zobrazil na displeji kde se zobrazuji paznaky protože je něco špatně. Ikdyž mi ponyprog tvrdí že texty začínají od adresy 0, kterou se snažím nastavit a číst z ní. Do těla cyklu jsem dal kod ktery mi rovněž vypisoval stavovy kod, ve vysledku se mi displej pomaloval napisy 0x50 coz svedci o tom ze z te EEPROMky nějaka data lezou, ale špatna. Podprogram pro vypis řadku na displej mám odladěný.

Je tu prosím někdo kdo těm EEPROMkám řady 24XXXXX rozumí a poradil by mi nebo spíš prozradil co dělám špatně?

Trochu off topic, ale neskusal si pouzit ATmega168 pripadne ATmega328?
Tvoj problem to uplne riesi aj ked trochu inym spoobom :slight_smile:

Postup pro čtení by měl být

i2c_start()
i2c_write(slave_address+Write)
i2c_write(adresa v eeprom)
i2c_start()
i2c_write(slave_address+Read)
i2c_readAck() // čti bajt z adresy v eeprom
i2c_readAck() // čti další bajt
i2c_readAck() // "


i2c_readNak() // čti poslední bajt

Kód najdeš tady v souboru twimaster.c
homepage.hispeed.ch/peterfleury/i2cmaster.zip

PS
Máš pull up odpory na SDA SCL?

:arrow_right: administrator: přiloženy externí soubory
i2cmaster.zip (23 KB)

Ano použil jsem vnitřní pull-upy, bohužel deska je již vyrobená, a použití vnější EEPROM se mi zdá jako nejjednoduší řešení co se týče konstrukce.

Přesně takový postup používám, ale data která přečtu neodpovídají. Ještě zkontroluji program. V zapojení podle mne chyba není protože ta paměť se mnou komunikuje, stavové kody to potvrzují. Spíš by mě zajímalo jestli je správně kód 0x10 a 0x40.

Děkuji za rozšíření obzoru. O těchto typech jsem neměl tušení.
Bohužel nejbližší kamenný obchod s elektronikou tyto typy nemá v nabídce, a objednávat se mi ho nechce. Ale díky za tip. Určitě je to řešení a pokud selže EEPROM, toto řešení použiji. První jsem myslel že ATmega168 je úplně jiná ale jak název napovídá je to atmega 8 s větší FLASH. Děkuji za info.

Pull-upy dám vnější, a vnitřní zakážu, doufám že už to půjde.

Připojím ještě ty vnější pull-upy,

Vnitřní pull up nestačí (má cca 20 - 50 kOhm).
Je třeba připojit vnější, typicky 4k7.

Nevím přesně,( nechce se mi to hledat) jaký odpor mají vnitřní pullupy, ale rozhodně bude mnohem vyšší než 4k7 doporučované pro I2C - z vlastní zkušenosti vím, že při PU 47k už to nefunguje.

AB byl rychlejší :slight_smile: .

Děkuji vaše rady pomohly. Dal jsem vnější pull-upy 4k7, opravil drobnou chybu v kódu a už to jede.

Ještě dotaz. Jak velký blok dat mohu najedonu zapsat nebo přečíst? Adresový čítač se inkrementuje automaticky, ale jak je to s adresou stránky.

Je možné si např. nastavit adresu 0x0200 a číst nebo zapisovat až do 0x02FF nebo jsem omezen ještě něčím?

Největší blok k psaní nebo čtení je 256 bajtů (0 - FFh).
Pak je třeba změnit stránku ve slave_address.

Šlo by také např. napsat funkci pro čtení, která bude adresovat celou paměť od 0 do 2047.

Toto nejde, adresa v eeprom je vždy jednobajtová (0 - FF).
Kombinací stránky (0-7) a adresy (0-255) dostaneš všech 2048 bajtů.

Jen připomínka k tvým příspěvkům - pokud možno neupravuj své starší příspěvky pozpátku, když už za nima je plno reakcí - někdo, kdo si otevře třeba až dnes v tom bude mít docela “hokej” že ti radíme to , co jsi vlastně udělal - třeba ty pullupy :slight_smile: - reaguješ úpravou příspěvku na odpovědi na něj.

No a nie je nahodou rozdiel medzi 0x0200 a 0x02FF prave tych FF?
Takze podla mna by to malo ist :slight_smile:

Rozdíl je opravdu FF, ale adresa 0x0200 v této paměti neexistuje.

Paměť je rozdělená do osmi stránek po 256 bajtech.
Adresu stránky nastavíme pomocí bitů 3,2,1 ve “slave_address”.
Adresu bajtu ve stránce určuje “adresa_v_eeprom”, která má rozsah 0-FFh.

Při zápisu musíme určit stránku i adresu ve stránce

//zápis do stránky 0
slave_address = 0b10100000;
i2c_start();
i2c_write(slave_address+Write); //stránka
i2c_write(adresa_v_eeprom); //adresa ve stránce

//zápis do stránky 1
slave_address = 0b10100010;
i2c_start();
i2c_write(slave_address+Write);
i2c_write(adresa_v_eeprom);

Ještě bych poznamenal, že za zhruba stejný peníz se dá koupit
24c32 nebo 64, které jsou adresovány souvisle dvoubajtovou adresou.

To uz som neskumal :slight_smile:

Je to tam napsáno: “adresa v eeprom je vždy jednobajtová”.