Článek stažen z HW server


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.


Vytisknout stránku Velikost 3 kByte

Zpátky
© DH servis 2002 -