Komunikace se sériovou pamětí typu 24C pro MCU51
Při návrhu zapojení se vyskytují případy, kdy je nutno uchovat po vypnutí napájení poměrně velké množství dat. V případě malého procesoru, jako jsou AT89C1051, AT89C2051, AT90S1200 nebo dokonce AT90S2343, je nutno použít sériové paměti. Sériové paměti typu 93C jsou dostupné pouze v malé kapacitě. Při požadavku na vyšší kapacitu přicházejí v úvahu sériové paměti typu 24C (128B až 64kB), využívající komunikace pouze pomocí dvou vodičů. Jedinou výhodou těchto pamětí není pouze ušetření vývodů procesoru, ale hlavně možnost na jeden komunikační kanál (hodiny a obousměrná data) osadit až osm těchto pamětí. Začátečníka asi velmi často odradí na první pohled složitý komunikační protokol, obousměrná datová linka a nutnost generovat a kontrolovat bit
zvaný ACK. Toto je složité skutečně pouze na první pohled.
Stručně řečeno, výhody typu 24C oproti 93C jsou asi následující.:
Pro komunikaci postačí pouze dva vodiče (SCL a SDA).
Na jednu komunikační linku je možno umístit až 8 pouzder (podle kapacity a výrobce!).
Mnohonásobně větší kapacita oproti typu 93C.
Používají zápisovou stránku až 64B, což umožňuje rychlé uložení velkého množství dat.
Jsou dostupné od mnoha výrobců (asi nejvíce ATMEL a MICROCHIP).
Pro dosavadní typy 24C postačí pouze dva typy komunikačních protokolů (ukázkový program).
Velmi vhodný poměr cena/kapacita (24C64 – 8kB za cca 40kč s DPH ).
Pro tyto a mnoho dalších výhod se vyplatí používat sériové
paměti typu 24C. Pro ty, kteří se zalekli (pouze na první pohled)
složitého komunikačního protokolu, uvádím celkem jednoduchý a názorný
příklad komunikace vytažený z programátoru všech typů sériových pamětí typu 24C.
Příklad je určen jak pro jednobytový tak i pro stránkový zápis a čtení. Než
stručně popíši ukázkový program, chtěl bych zdůraznit některé podstatné rozdíly
těchto pamětí od různých výrobců. Než použijete sériovou paměť (hlavně pro začátečníky)
typu 24C, je třeba zjistit následující vlastnosti (srovnány zhruba podle důležitosti):
Jak velká je zápisová stránka pro zvolenou
kapacitu paměti. Pohybuje se od 2B do 64B. Tento parametr udává kolik bytů
je možno zapsat do paměti najednou a poté teprve odstartovat zápis (zápis je
odstartován vygenerováním STOP značky). Tento parametr velmi urychluje zápis.
Zápis (vlastní uložení) stránky trvá stejný čas, jako uložení jednoho bytu.
Pokud zapíšete do paměti najednou více bytů, než je kapacita stránky, dojde
k přepisování stránky opět od začátku a tím zničení dat na začátku stránky.
(Při čtení paměti nemá velikost stránky žádný vliv.)
Zda jsou použity
nebo nepoužity výběrové vstupy A0, A1 a A2 pouzdra paměti. Pouzdro paměti obsahuje tři
výběrové vstupy označené A0, A1 a A2. Při komunikaci s pamětí je nutno v adrese udat
stav těchto vstupů (pokud jsou interně zapojeny). Pokud paměť rozpozná v přišlé adrese
své nastavení, potvrdí adresaci bitem zvaným ACK (jinak ne). Pokud chcete použít na
jednom kanále více pamětí typu 24C, velmi dobře prostudujte, zda zvolený výrobce tyto
vstupy skutečně používá. Například 24C04 od ATMELu tyto vstupy používá, ale od MICROCHIPu
ne! Možná novější verze již ano, nevím. Tato chyba se těžko hledá, když studujete popis
paměti, která je jiná, než jste skutečně použili.
Dobré je i zjistit
potřebný čas pro zápis (pro byte a stránku jsou většinou stejné). U novějších pamětí 24C
se již udává mnohem menší zápisový čas (někde pouhé 2ms), ale toto se také liší podle
výrobce. Při použití pamětí od různých (na jednom kanále, nebo při několika kusové výrobě)
je nutno na toto brát ohled.
Pozor na skutečnost,
že různí výrobci tyto paměti až znatelně vylepšují (24C65 je z hlediska základu totožná s
24C64, ale obsahuje například možnost zablokování/heslování interních dat).
Podle zde uvedených doporučení, by se opět mohl zdát použití pamětí typu 24C složité. Je třeba si prohlédnout potřebnou dokumentaci a porozumět jejich činnosti. Jako vhodnou dokumentaci bych doporučil od ATMELu na WWW.ATMEL.COM. Já osobně jsem použil paměť typu 93C poprvé před asi třemi lety a také naposled pro její malou kapacitu a „složité“ ovládání (čtyři nebo tři vodiče a mnoho povelů).
Popis přiloženého programu :
Nebudu zde popisovat princip komunikace po SCL a SDA mezi procesorem a pamětí,
toto lze najít třeba na uvedené adrese. Stručně popíši ukázkový program,
který najdete přiložen k tomuto příspěvku. Obecný program lze jistě zmenšit,
pokud bude požadováno připojení pouze jedné paměti a pouze bytový nebo stránkový zápis.
Zde je však uvedena přehledná varianta pro začátečníky v oboru zvaném 24C.
Nejprve jsou uvedeny použité bitové a bytové adresy a konstanty:
AT24C32 (AT je uvedeno pouze z důvodu, že název nemůže začínat číslem a neznamená žádná omezení na paměti od AMELu). Tímto bitem se rozlišuje, zda se komunikuje s pamětí 24C01/02/04/08/16 (AT24C32=0), nebo s 24C/32/64/128/256/512 (AT24C32=1). Pro tyto dvě skupiny pamětí se poněkud liší zasílaný paket (pouze do paměti).
I2C_ERROR Udává, zda komunikace proběhla v pořádku (I2C_ERROR=0), nebo nastala nějaká chyba (I2C_ERROR=1). Tento příznak je nutno po každé komunikaci otestovat a nulovat.
I2C_END Tento bit se používá pouze při čtení/zápisu několika bytů najednou. Hodnota I2C_END=1 udává, že se bude číst poslední byte z paměti a je tedy nutno generovat neplatný ACK (pouze při čtení z paměti) následovaný STOP značkou. Pokud je I2C_END=0 znamená to, že se při čtení generuje platný ACK (bude následovat ještě další požadavek na čtení) a nevytváří se STOP značka. STOP značka se vytváří pouze při ukončení (třeba i několika bytového) čtení (po té co byl generován neplatný ACK) a při ukončení zápisu (jak bytu, tak i stránky) pro zahájení (samo)zápisu. Při použití čtení/zápis pouze jednoho bytu není nutno I2C_END nastavovat.
I2C_ACK Používán pouze při přímém přístupu ke komunikaci. Z vyšší sféry netřeba uvažovat. (Požadovaný přímý stav generovaného ACK při vysílání, nebo přímý stav přijatého ACK. Nerad bych toto zamlžil, ale je třeba říci, že platný ACK je ve skutečnosti log.0).
I2C_SELECT Zde v bitech 2,1,0 musí být uveden stav výběrových vstupů pouzdra obvodu označených A2, A1, A0. Pro první pokusy doporučuji naplnit tuto adresu hodnotou 00h a výběrové vstupy zapojit na log.0. (Ne všechny paměti používají všechny výběrové vstupy. Toto záleží na kapacitě a výrobci.)
ADR_LOW a ADR_HIGH Do těchto bytů je třeba uložit adresu, ze které se bude v paměti 24C číst, nebo na kterou se bude do paměti 24C zapisovat. Pozor na maximální dovolenou adresu (pro paměti 24C32/64/128/256/512 budou po překročení adresy přepisovány počátečný adresy, ale pro 24C01/02/04/08/16 může dojít k vytvoření chybného paketu). Je dobré si prohlédnout formát paketu a způsob vytváření ve zde popisovaném příkladu a vše bude jasné.
I2C_POCET Zde je třeba nastavit počet čtených/zapisovaných bytů při vícebytovém přístupu (minimálně dva).
I2C_TEMP Pro dočasné uložení vysílané hodnoty.
I2C_SPEED Konstanta pro vytvoření zpoždění při vytváření komunikační frekvence. Nastavujeme podle odhadu z údajů výrobce a rychlosti procesoru.
SCL Výstup hodin komunikačního kanálu (zde pouze výstup).
SDA Vstupně/výstupní data komunikačního kanálu.
Ukázkový program je vytvořen pro možnost okamžitého použití (po nastavení uvedených hodnot). Nejprve je proveden zápis do 24C32 (nebo vyšší), poté je vykonáno čtení. Přečtená hodnota je uložena na adresu 05h a stav I2C_ERROR předán na P1.7 (možno změřit). Pokud po připojení paměti například 24C64 spustíme program a na portu P1.7 je log.0, je vše v pořádku a můžeme začít s vylepšováním pro své použití.
Zápis jednoho bytu z vyšší úrovně je velmi jednoduchý a nepotřebuje vysvětlení. Totéž platí pro čtení jednoho bytu.
Zápis několika hodnot :
V tomto ukázkovém příkladě pouze do velikosti jedné stránky. Nejprve je nastaven počet zapisovaných bytu, poté adresa v paměti 24C a nakonec adresa v interní paměti procesoru, odkud se budou byty pro zápis do 24C vyzvedávat. Nejprve se do paměti zapíše kontrolní byte, adresa od které se bude číst a rovnou i jedna hodnota (viz. dokumentace k 24C). Toto se ale nesmí ukončit STOP značkou, protože by začal interní zápis v paměti. Je tedy nutno nastavit I2C_END=0. Nyní se do.paměti postupně zapisují další byty (maximálně v délce stránky). Teprve po zápisu posledního je nastaveno I2C_END=1 pro vygenerování STOP značky a paměť 24C v tento okamžik zahájí zápis (ukládání) celé přijaté stránky. (Při zápisu do paměti všechny bity ACK generuje paměť a úkolem komunikačního programu je kontrolovat, zda paměť skutečně zápis všech hodnot potvrzuje platným ACK. Toto se děje na nižší úrovni a výše se oznamuje pomocí I2C_ERROR.)
Čtení hodnot :
Počet čtených bytů vůbec nezáleží na velikosti „zápisové“ stránky, a proto je možno paměť vyčíst od adresy 0000h najednou (stále číst a teprve nakonec vygenerovat STOP značku). Mezi čtenými byty může být libovolná časová pauza.
ACK bit generuje příjemce. Při čtení tedy ACK generuje procesor. Tímto paměti po každém přečteném bytu oznamuje, zda byl poslední (neplatné ACK) nebo bude požadovat ještě další (platné ACK). Pozor na skutečnost, že není možno čtení vždy ukončit pouze vygenerováním STOP značky, která (podle dokumentace) ukončuje komunikaci. (Pro vygenerování STOP značky je nutno zvednout SDA na log.1 (při SCL v log.1), což nemusí být vždy možné. Pokud procesor paměti potvrdí přijatá data pomocí platného ACK, tak při spádové hraně SCL již paměť vysouvá další data. První bit nového bytu může mít hodnotu log.0, kterým paměť přidrží SDA v log.0 do příští spádové hrany SCL, aby jej procesor mohl přečíst a není možno vygenerovat STOP značku. Paměť tedy zablokuje SDA, tím že již poskytuje další data. Toto je častá chyba.)
Nerad bych zde popisoval celou komunikaci, která je dostupná v dokumentaci. Ukázkový program je dosti okomentovaný a proto na závěr uvedu pouze stručné vysvětlení částí nižší (ne nejnižší) úrovně komunikace.
Pro zápis do paměti je třeba dodržet následující posloupnost:
- Vygenerovat START značku.
- Zapsat kontrolní slovo, které obsahuje nastavení výběrových vstupů pouzdra, příznak pro zápis a u pamětí 24C01/02/04/06/16 i vyšší bity adresy.
- Zbylou část adresy pro 24C01/02/04/08/16, ale teprve celou adresu pro 24C32/64/128/256/512.
- Postupně zapsat požadovaný počet bytů (maximálně velikost stránky).
- Vygenerovat STOP značku. (Nyní začíná interní zápis v paměti.)
Pro čtení platí následující posloupnost:
- Vygenerovat START značku.
- Zapsat kontrolní slovo, které obsahuje nastavení výběrových vstupů pouzdra, příznak pro zápis (bude se zapisovat adresa, od které se bude číst) a u 24C/01/02/04/08/16 i vyšší bity adresy.
- Zbylou část adresy pro 24C01/02/04/08/16, ale teprve celou adresu pro 24C32/64/128/256/512.
- Vygenerovat STOP, čímž dojde k zápisu do interního čítače adres (ne na adresu).
- Vygenerovat START značku (*).
- Zapsat kontrolní slovo, které obsahuje nastavení výběrových vstupů pouzdra, příznak pro čtení (již se budou číst hodnoty).
- Postupné čtení hodnot a potvrzování ACK.
- Po poslední požadované hodnotě ACK nepotvrdit.
- Vygenerovat STOP značku.
(*) S každým přečteným bytem se interní čítač adres zvětšuje o jedničku. Pokud postupné čtení skončíme na určité adrese a poté požadujeme pokračovat dále, stačí začít čtení od tohoto okamžiku (poslední adresa je zachována).
;Stazeno z www.HW.cz
; Autorem tohoto SW je Petr Novak - Novak@hw.cz
;------------------------------------------------------------------------------
; ### POUZITE BYTY A BITY ###
;------------------------------------------------------------------------------
AT24C32 EQU 8 ; (bit)
; =0 pro 24C01/02/04/08/16
; =1 pro 24C32/64/128/256/512
I2C_ERROR EQU 9 ; (bit) nebyl prijat platny ACK
I2C_END EQU 10 ; (bit) =1 bude se cist posleni byte
I2C_ACK EQU 11 ; (bit) zapisovany/cteny ACK bit
I2C_SELECT EQU 8 ; (byte) nastaveni vyberovych vstupu A0,A!,A2
ADR_LOW EQU 9 ; (byte) nastavena adresa rpo zapis/cteni
ADR_HIGH EQU 10 ; (byte)
I2C_POCET EQU 11 ; (byte) pocet zapisovenych/ctenych bytu
I2C_TEMP EQU 12 ; (byte) ulozeni vysilane hodnoty
I2C_SPEED EQU 10 ; konstanta
; prirazeni pinu
SCL EQU P1.0 ; CLK pro I2C
SDA EQU P1.1 ; DATA pro I2C
;------------------------------------------------------------------------------
; ### MAKRA ###
;------------------------------------------------------------------------------
; cekaci cas 2x I2C)SPEED (us)
; vstup: I2C_SPEED - pocet cekani v (2 * us)
DELAY MACRO
mov 13,#I2C_SPEED ; pozadovana delka cekani
djnz 13,$ ; a jeho vytvoreni
ENDM
;------------------------------------------------------------------------------
; **** ukazkove programy ****
TABULKA1 EQU 120 ; zapisovane hodnoty (interni RAM)
TABULKA2 EQU 50 ; ctene hodnoty (interni RAM)
mov sp,#100 ; zasobnik
; nastaveni pro seriovou pamet
setb AT24C32 ; bude to 24C64
mov I2C_SELECT,#00 ; vstupy A0,A1,A2 zapojeny na log.0
clr I2C_ERROR ; zatim neni chyba
; zapis jedne hodnoty na danou adresu
mov ADR_LOW,#34h ; na adresu 1234h
mov ADR_HIGH,#12h
mov A,#12h ; zapis hodnotu ABh
call WRITE_BYTE
; cteni jedne hodnoty z dane adresu
mov ADR_LOW,#34h ; z adresy 1234h
mov ADR_HIGH,#12h
call READ_BYTE ; precti hodnotu do ACC
mov C,I2C_ERROR ; stav I2C_ERROR -> Carry
mov P1.7,C ; Carry -> P1.7
mov 05,A ; ctenou hodnotu ulozit an adresu 05
jmp $ ; konec
; zapis nekolika hodnot od dane adresy
mov I2C_POCET,#10 ; zapis 10 bytu
mov ADR_LOW,#34h ; od adresy 1234h
mov ADR_HIGH,#12h
mov R0,#TABULKA1 ; ktere jsou ulozeny v TABULKA1
clr I2C_END ; zatim neni konec zapisu
mov A,@R0 ; vyzvednuti prvni hodnoty
call WRITE_BYTES ; zapis adresy + prvni byte
jb I2C_ERROR,WRI03 ; pokud pamet neodpovida -> chyba
dec I2C_POCET ; jeden byte byl jiz zapsan
WRI01: djnz I2C_POCET,WRI02 ; pokud dalsi bude posledni byte
setb I2C_END ; tak nastav priznak konce zapisu
WRI02: inc R0 ; posun ukazatele pro cteni hodnot
mov A,@R0 ; vyzvednuti dalsi hodnoty
call WRITE_NEXT ; zapis dalsi hodnoty (pokud posledni -> STOP)
jb I2C_ERROR,WRI03 ; pokud pamet neodpovida -> chyba
jnb I2C_END,WRI01 ; jinak pokracuj dalsi hodnotou
WRI03: ; kontrola zda neni I2C_ERR
; cteni nekolika hodnot od dane adresy
mov I2C_POCET,#10 ; cteni 10 bytu
mov ADR_LOW,#34h ; od adresy 1234h
mov ADR_HIGH,#12h
mov R0,#TABULKA2 ; ktere se budou ukladat TABULKA2
clr I2C_END ; zatim neni konec cteni
call READ_BYTES ; zapis adresy + cteni prvniho byte
mov @R0,A ; ulozeni prvni prectene hodnoty
jb I2C_ERROR,REA03 ; pokud pamet neodpovida -> chyba
dec I2C_POCET ; jeden byte byl jiz zapsan
REA01: djnz I2C_POCET,REA02 ; pokud dalsi bude posledni byte
setb I2C_END ; tak nastav priznak konce cteni
REA02: inc R0 ; posun ukazatele pro zapis hodnot
call READ_NEXT ; cteni dalsi hodnoty (pokud posledni -> STOP)
mov @R0,A ; ulozeni dalsi prectene hodnoty
jnb I2C_END,REA01 ; jinak pokracuj dalsi hodnotou
REA03: ; kontrola zda neni I2C_ERR
;------------------------------------------------------------------------------
; ### KOMUNIKACE s 24C ###
;------------------------------------------------------------------------------
READ_BYTE: ; vstup pro cteni jedne adresy udane v ADR_LOW a ADR_HIGH do ACC
setb I2C_END ; pouze tento byte
READ_BYTES: ; vstup pro cteni POCET bytu od adresy ADR_LOW a ADR_HIGH
; zapis adresy ze ktere se bude cist
call I2C_START ; START na I2C
call I2C_DEVICE_WR ; vyslani DEVICE bytu + WRITE
jb I2C_ACK,I2C_ERR ; pokud pamet nedala ACK=0 -> CHYBA
call I2C_ADR_WR ; zapis adresy
jb I2C_ACK,I2C_ERR ; pokud pamet nedala ACK=0 -> CHYBA
call I2C_STOP ; STOP na I2C
; zahajeni cteni
call I2C_START ; START na I2C
call I2C_DEVICE_RD ; vyslani DEVICE bytu + READ
jb I2C_ACK,I2C_ERR ; pokud pamet nedala ACK=0 -> CHYBA
READ_NEXT: ; vstup pro cteni dalsicho bytu do ACC
mov C,I2C_END ; Carry=1 pokud se bude cist posledni byte
mov I2C_ACK,C ; pokud Carry=1 -> ACK=1 -> posledni cteni
call I2C_IN ; cteni bytu z I2C
jnb I2C_END,READ_01 ; pokud to neni posledni cteny byte -> skok
call I2C_STOP ; jinak STOP na I2C
READ_01: ret ; navrat
;------------------------------------------------------------------------------
WRITE_BYTE: ; vstup pro zapis na jednu adresu udanou ADR_LOW a ADR_HIGH z ACC
setb I2C_END ; pouze jedna hodnota
WRITE_BYTES: ; vstup pro zapis nekolika hodnot od ADR_LOW a ADR_HIGH, prvni v ACC
mov I2C_TEMP,A ; uchovat vysilanou hodnotu
; zapis adresy na kterou se budou byty ukladat
call I2C_START ; START na I2C
call I2C_DEVICE_WR ; vyslani DEVICE bytu + WRITE
jb I2C_ACK,I2C_ERR ; pokud pamet nedala ACK=0 -> CHYBA
call I2C_ADR_WR ; zapis adresy
jb I2C_ACK,I2C_ERR ; pokud pamet nedala ACK=0 -> CHYBA
; zapis vsech prijatych hodnot
mov A,I2C_TEMP ; vyzvednou vysilanou hodnotu
WRITE_NEXT: ; vstup pro zapis da;lsi hodnoty z ACC
call I2C_OUT ; vyslani hodnoty
jb I2C_ACK,I2C_ERR ; pokud pamet nedala ACK=0 -> CHYBA
jnb I2C_END,WRITE_02 ; pokud neni posledni hodnota -> skok
call I2C_STOP ; jinak STOP na I2C
; cekani na zapis (mozno zaremovat pokud se mezitim neco vykonava)
mov B,#20 ; asi 10ms pro 12MHz (podle typu)
WRITE_01: mov A,#255 ; 0.5ms
djnz ACC,$
djnz B,WRITE_01
WRITE_02: ret ; navrat
I2C_ERR: ; hlaseni chyby ze pamet neodpovida
call I2C_STOP ; STOP na I2C
setb I2C_ERROR ; chyba = SER. PAMET NEODPOVIDA
ret ; navrat pri chybe
;------------------------------------------------------------------------------
; ### PODPROGRAMY PRO SERIOVE PAMETI 24C ###
;------------------------------------------------------------------------------
; vytvoreni STARTu na I2C
I2C_START: push ACC ; uchovej ACC
clr SDA ; SDA jde do log.0 zatim co je SCL=1 -> START
DELAY ; cekej
clr SCL ; SCL=1 (klidovy stav na I2C)
mov A,#100 ; celej
djnz ACC,$
pop ACC ; obnov ACC
ret ; navrat z podprogramu
;------------------------------------------------------------------------------
; vytvoreni STOPu na I2C
I2C_STOP: push ACC ; uchovej ACC
clr SDA ; SDA=0 = klidovy stav
mov A,#50 ; celej
djnz ACC,$
setb SCL ; SCL=1 (pred zmenou SDA)
DELAY ; cekej
setb SDA ; SDA jde do log.1 zatim co je SCL=1 -> STOP
mov A,#100 ; celej
djnz ACC,$
pop ACC ; obnov ACC
ret ; navrat z podprogramu
;------------------------------------------------------------------------------
; vyslani DEVICE bytu s priznakem R/W
; (24C01/02/04/08/16),(24C32/64/128/256/512)
I2C_DEVICE_RD: ; vstup pro cteni hodnot
mov A,#00000001b ; READ
jmp I2C_WRITE
I2C_DEVICE_WR: ; vstup pro zapis hodnot
mov A,#00000000b ; WRITE
I2C_WRITE: ; vstup pri zapisu
orl A,I2C_SELECT ; nastaveni SELECTovacich pinu
orl A,#10100000b ; DEVICE ADDRESS
jb AT24C32,I2C_W1 ; pokud jde o 24C32/64/128/256/512 -> skok
mov B,A ; uschovej ACC
mov A,ADR_HIGH ; HIGH cast adresy -> ACC
rl A ; posun do bitu 3,2,1
orl A,B ; a pricti k DEVICE ADDRESS
I2C_W1: call I2C_OUT ; vyslat
ret ; navrat z podprogramu
;------------------------------------------------------------------------------
; zapis adesy do ser. pameti
; (24C01/02/04/08/16),(24C32/64/128/256/512)
; vstup: DPTR (DPL) -> adresa pro zapis do ser. pameti
I2C_ADR_WR:
jnb AT24C32,I2CAW1 ; pokud nejde o 24C32/64/128/256 -> skok
mov A,ADR_HIGH ; HIGH cast adresy
call I2C_OUT ; vyslat
jb I2C_ACK,I2CAW2 ; pokud ACK=1 -> chyba
I2CAW1: mov A,ADR_LOW ; LOW cast adresy
call I2C_OUT ; vyslat
I2CAW2: ret ; navrat z podprogramu
;------------------------------------------------------------------------------
; skutecne vysilani/prijem na I2C
; vstup: ACC -> vysilana (OUT)/prijata(IN) hodnota
; vystup: I2C_ACK -> prijaty(OUT)/vysilany(IN) ACK
I2C_IN: ; prijem bytu z I2C s vyslanim ACK
mov A,#11111111b ; bude se prijimat
jmp I2C_OUT1
I2C_OUT: ; vyslani bytu na I2C s prijmem ACK
setb I2C_ACK ; ACK se bude prijimat
I2C_OUT1: mov B,#8 ; bude 8 bitu
I2C_OUT2: rlc A ; ACC.7 -> Carry
mov SDA,C ; Carry -> SDA
DELAY ; cekej
setb SCL ; SCL=1 (zacatek zapisu dat)
DELAY ; cekej
mov C,SDA
clr SCL ; SCL=0 (konac zapisu dat)
DELAY ; cekej
djnz B,I2C_OUT2 ; vyslat vsech 8 bitu
rlc A ; posledni prijaty bit do ACC
mov C,I2C_ACK ; stav ACK -> Carry
mov SDA,C ; Carry -> SDA
DELAY ; cekej
setb SCL ; SCL=1 (pro zacatek prijeti ACK)
DELAY ; cekej
mov C,SDA ; stav ACK -> Carry
mov I2C_ACK,C ; Carry -> I2C_ACK
clr SCL ; SCL=0 (pro ukonceni prijeti ACK)
DELAY ; cekej
setb SDA ; radsi SDA=1
ret ; navrat z podprogramu
;------------------------------------------------------------------------------
end
;Stazeno z www.HW.cz
;Autorem tohoto SW je Petr Novak - Novak@hw.cz
A na závěr jednu radu. Používejte součástky, které dodává více výrobců a prodejen. Ušetříte si tím za nějaký čas trápení při hledání náhrady, když jeden výrobce jejich produkci ukončí. Rovněž používejte součástky, které lze v budoucnu velmi snadno nahradit lepšími. Toto například platí o řadě 24C, kde jsou shodná pouzdra, zatím pouze dva jen mírně se lišící pakety, ale hlavně kapacita se zvyšuje podle potřeby. Pro zařízení na zakázku používám pouze řadu 24C. Zákazník může přijít za nějaký čas s prosbou o uchovávání mnohem většího množství dat. Nedávno jsem měnil pouze 24C32 za 24C256 a prodlužoval čas měření v odlehlém procesoru, který na požádání vyšle data po RS485. Tato úprava by byla při použití 93C téměř neproveditelná. Většinu zákazníků nezajímá jak pracná byla úprava, ale hlavně že je. Vývojář si ušetří mnoho práce, když myslí dopředu a navíc k němu zákazník získá důvěru.
| |
|
|
© DH servis 2002 - |