PIC 16F628A a externí EEPROM 24C64

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Odpovědět
Zpráva
Autor
tmm

PIC 16F628A a externí EEPROM 24C64

#1 Příspěvek od tmm »

Zdravím,
potøeboval bych poradit ohlednì komunikace s externí EEPROM pomocí I2C - myslím si, že kód mám správnì napsaný, pøesto z nìjakého dùvodu nedochází ke správnému zápisu (resp. žádnému) a se ètením to je podobné :(

Kód: Vybrat vše

; Pøeète 1 byt a uloží ho do promìnné EBYTE
@i2c_in_byte
        CALL    @i2c_high_sda

        MOVLW   8
        MOVWF   rot
i2c_in_byte_rot ; Uložíme pøichozí bit do C a rotací jej dostaneme do EBYTE - takto zopakujem 8 krát pro celý byte
        CALL    @i2c_high_scl
        BTFSS   SDA
        GOTO    $+3
        BSF     STATUS,C
        GOTO    $+2
        BCF     STATUS,C

        CALL    @i2c_low_scl

        RRF     EBYTE,1
        DECFSZ  rot,1
        GOTO    i2c_in_byte_rot

        RETLW   0

;---------------------------------------------------------

; Odešle 1 byt (promìnná EBYTE)
@i2c_out_byte
        MOVLW   8
        MOVWF   rot
i2c_out_byte_rot ; Rotací EBYTE pøes Carry Flag odešleme postupnì všechny bity
        RRF     EBYTE,1

        BTFSS   STATUS,C
        GOTO    $+3
        CALL    @i2c_high_sda
        GOTO    $+2
        CALL    @i2c_low_sda

        CALL    @i2c_high_scl
        CALL    @i2c_low_scl

        DECFSZ  rot,1
        GOTO    i2c_out_byte_rot

        CALL    @i2c_high_sda
        RETLW   0

;---------------------------------------------------------

@i2c_nack
        CALL    @i2c_high_sda
        CALL    @i2c_high_scl
        CALL    @i2c_low_scl
        RETLW   0

@i2c_ack
        CALL    @i2c_low_sda
        CALL    @i2c_high_scl
        CALL    @i2c_low_scl
        ;CALL    @i2c_high_sda
        RETLW   0

@i2c_start
        CALL    @i2c_low_scl
        CALL    @i2c_high_sda
        CALL    @i2c_high_scl
        CALL    @i2c_low_sda
        CALL    @i2c_low_scl
        RETLW   0

@i2c_stop
        CALL    @i2c_low_scl
        CALL    @i2c_low_sda
        CALL    @i2c_high_scl
        CALL    @i2c_high_sda
        CALL    @i2c_low_scl
        RETLW   0      

@i2c_high_sda
        BSF     STATUS,RP0      ; Banka 1      
        BSF     SDADIR          ; SDA vstup
        BCF     STATUS,RP0      ; Banka 0
        CALL    @delay_50us
        RETLW   0

@i2c_low_sda
        BCF     SDA             ; SDA = 0
        BSF     STATUS,RP0      ; Banka 1
        BCF     SDADIR          ; SDA výstup
        BCF     STATUS,RP0      ; Banka 0
        CALL    @delay_50us
        RETLW   0

@i2c_high_scl
        BSF     STATUS,RP0      ; Banka 1
        BSF     SCLDIR          ; SCL vstup
        BCF     STATUS,RP0      ; Banka 0
        CALL    @delay_50us
        RETLW   0

@i2c_low_scl
        BCF     SCL             ; SCL = 0
        BSF     STATUS,RP0      ; Banka 1
        BCF     SCLDIR          ; SCL výstup
        BCF     STATUS,RP0      ; Banka 0
        CALL    @delay_50us
        RETLW   0

@delay_50us
        MOVLW   16
        MOVWF   cd1      
        DECFSZ  cd1,1
        GOTO    $-1
        RETLW   0

Pro zápis pak používám:

Kód: Vybrat vše

        CALL    @i2c_start

        ; Device Address
        MOVLW   B'1010000'
        MOVWF   EBYTE
        CALL    @i2c_out_byte
        CALL    @i2c_nack

        ; First Word Address
        MOVLW   H'00'
        MOVWF   EBYTE
        CALL    @i2c_out_byte
        CALL    @i2c_nack

        ; Second Word Address (EADR adresa pro zápis)
        MOVF    EADR,W
        MOVWF   EBYTE
        CALL    @i2c_out_byte
        CALL    @i2c_nack

        ; Data
        MOVLW   H'88'
        MOVWF   EBYTE
        CALL    @i2c_out_byte
        CALL    @i2c_nack

        CALL    @i2c_stop
Pro ètení:

Kód: Vybrat vše

        CALL    @i2c_start

        ; Device Address
        MOVLW   B'1010000'
        MOVWF   EBYTE
        CALL    @i2c_out_byte
        CALL    @i2c_nack

        ; First Word Address
        MOVLW   H'00'
        MOVWF   EBYTE
        CALL    @i2c_out_byte
        CALL    @i2c_nack

        ; Second Word Address
        MOVF    EADR,W
        MOVWF   EBYTE
        CALL    @i2c_out_byte
        CALL    @i2c_nack

        CALL    @i2c_start

        ; Device Address
        MOVLW   B'1010001'
        MOVWF   EBYTE
        CALL    @i2c_out_byte
        CALL    @i2c_nack

        CALL    @i2c_in_byte

        CALL    @i2c_stop
Kód mám pøepsaný z netu, nìkolikrát jsem to kontroloval a chybu jsem nenašel. Mùžete nìkdo poradit?

Uživatelský avatar
Atlan
Příspěvky: 4499
Registrován: 10 kvě 2004, 02:00
Bydliště: Košice

#2 Příspěvek od Atlan »

;************************************i2c komunikacia******************
I2Cstart
bsf sda ;ini dAta v W registre
bsf scl
call outsda ;sda je nastavene na vystup
call cek10
bcf sda ;start
call cek10
bcf scl ;ukoncena start sekvencia
return

i2cW
movwf pom
call outsda ;sda je nastavene na vystup
movlw 8
movwf cykl
cyklusI2C
call cek10
bcf scl
call cek10
bcf sda
call cek10
rlf pom,1
btfsc STATUS,C
bsf sda
call cek10
bsf scl
decfsz cykl,1
goto cyklusI2C

acks
call cek10
bcf scl ;acklovage
call insda ;sda je nastavene na vstup
call cek10
bsf scl
btfsc sda ;TEST ci bol prikaz potvrdeny...
goto $-1
call cek10
bcf scl
return
;-----------------------------------------------------------
i2cR
call insda ;sda je nastavene na vstup
movlw 8
movwf cykl
call cek10
bsf scl
btfsc sda
incf dat,1
bcf STATUS,C
rlf dat,1
call cek10
bcf scl
decfsz cykl,1
goto $-9
rrf dat,1 ;oprava prevodu
movf dat,0
movwf dati2c
clrf dat
return

ackm
call outsda ;sda je nastavene na vystup
bcf sda
call cek10
bsf scl
call cek10
bcf scl
call cek10
call insda ;sda je nastavene na vstup
bsf sda
call cek10
return

I2Cstop
call cek10
call outsda ;sda je nastavene na vystup
bcf sda ;ukoncena stop sekvencia
call cek10
bsf scl ;stop
call cek10
bsf sda ;ukoncena stop sekvencia
call insda ;sda je nastavene na vstup
call cek10
return
;********************************************************
insda
bsf STATUS,RP0 ; banka registru 1
bsf TRISA,3 ;sda je nastavene na vstup
bcf STATUS,RP0 ; banka registru 0
return
outsda
bsf STATUS,RP0 ; banka registru 1
bcf TRISA,3 ;sda je nastavene na vystup
bcf STATUS,RP0 ; banka registru 0
return
;************************ LCD ***************************
;----------------------------------------- zapis do eprom -----------
epromw
call I2Cstart
movlw b'10100010' ;ide o zapis do 24c64; adresa 24c64
call i2cW
;-----------------------------------------
movfw adresah ; adresa high
call i2cW
movfw adresal ; adresa low
call i2cW
movfw dati2c
call i2cW
call I2Cstop
call cek15m
return
;******************************************************************
epromk call I2Cstart
movlw b'10100010' ;ide o zapis do 24c64; adresa 24c64
call i2cW
movfw adresah ; adresa high
call i2cW
movfw adresal ; adresa low
call i2cW
call I2Cstart
movlw b'10100011' ;ide o citanie z 24c64; adresa 24c64
call i2cW
;-----------------------
call i2cR
return

Uživatelský avatar
Atlan
Příspěvky: 4499
Registrován: 10 kvě 2004, 02:00
Bydliště: Košice

#3 Příspěvek od Atlan »

Akosi tam nevidim kde testujes ACK od slave ?????

tmm

#4 Příspěvek od tmm »

Jak dlouho trvá prosimtì ten cyklus cek10 ?
Ještì bych rád vedìl, jaký jestli je nìjaký speciální dùvod nastavovat po stop sekvenci SDA jako vstup ...

Zkoušel jsem ten tvùj kód, ale poøád nvm, kde dìlám chybu - mùžeš mi to prosímtì zkontrolovat? Zacyklím se pøi èekání na ACK od EEPROMky ...

Kód: Vybrat vše

@i2c_start
        BSF     STATUS,RP0
        BCF     SDADIR          ; SDA výstup
        BCF     STATUS,RP0
        BSF     SDA

        BSF     SCL
        GOTO    $+1
        GOTO    $+1
        GOTO    $+1
        BCF     SDA
        GOTO    $+1
        GOTO    $+1
        GOTO    $+1
        BCF     SCL
        RETLW   0

Kód: Vybrat vše

@i2c_write 
        MOVWF   EBYTE ; Data k zaslani do W
        MOVLW   8 
        MOVWF   rot ; Pocet bitu k zaslani
i2c_write_rot
        RLF     EBYTE,1
        BCF     SCL

        BTFSS   STATUS,C 
        GOTO    $+3 
        BSF     SDA
        GOTO    $+2 
        BCF     SDA

        NOP
        BSF     SCL

        NOP

        DECFSZ  rot,1 
        GOTO    i2c_write_rot
        
        CALL    @i2c_ack

        RETLW   0

Kód: Vybrat vše

@i2c_ack
        BCF     SCL
        BSF     STATUS,RP0      
        BSF     SDADIR          ; SDA vstup
        BCF     STATUS,RP0
        GOTO    $+1
        BSF     SCL

        GOTO    $+1
        GOTO    $+1
        NOP

        BTFSC   SDA
        GOTO    $-1

        NOP
        BCF     SCL
        BSF     STATUS,RP0
        BCF     SDADIR          ; SDA výstup
        BCF     STATUS,RP0
        RETLW   0

Uživatelský avatar
Atlan
Příspěvky: 4499
Registrován: 10 kvě 2004, 02:00
Bydliště: Košice

#5 Příspěvek od Atlan »

@i2c_write
MOVWF EBYTE ; Data k zaslani do W
MOVLW 8
MOVWF rot ; Pocet bitu k zaslani
i2c_write_rot
RLF EBYTE,1


BTFSS STATUS,C
GOTO $+3
BSF SDA
GOTO $+2
BCF SDA


BSF SCL
call wait 10 ;caa 10mikros
BCF SCL
call wait 10

NOP

DECFSZ rot,1
GOTO i2c_write_rot


CALL @i2c_ack

RETLW 0

@i2c_ack
; BCF SCL
BSF STATUS,RP0
BSF SDADIR ; SDA vstup
BCF STATUS,RP0
GOTO $+1
BSF SCL


GOTO $+1
GOTO $+1
NOP

BTFSC SDA
GOTO $-1

NOP
BCF SCL
call wait 10

BSF STATUS,RP0
BCF SDADIR ; SDA výstup
BCF STATUS,RP0
RETLW 0


cek10 alebo 10mikros ;zavisi od rychlosti komunikacie eprom 100/300khz Dost dolezite...lebo ti nebude eprom stihat reagovat ked to budes ladovat 1MHz (4Mhz taktovany)

Po stope sda na vstup ..nieje ziadny dovod ja len aby nejakym skratom a tak neodpalil....

Este takato vec.... najprv prednastav porty na log1 a az potom ich zadefinuj ako i/o....... tj najprv bsf portA,0 a az potom bsf alebo bcf TRISA,0.

Lebo pri zapniti pic su i/o v vysokej impedancii.... aby si nahodou nespustil starrt impulz ani nevieš ako ....:)

P.S. dufam ze mas Pullup odpory na sda priapdne scl.... hlavne ked to mas na RA4.
Naposledy upravil(a) Atlan dne 11 pro 2008, 16:47, celkem upraveno 2 x.

Uživatelský avatar
vilem
Příspěvky: 13
Registrován: 11 pro 2008, 01:00

#6 Příspěvek od vilem »

Dobrý den

dal by se tento postup(program) použít i pro paměti EEPROM 24C1024 ??

Děkuji.

Uživatelský avatar
Mendor
Příspěvky: 223
Registrován: 16 dub 2008, 02:00
Bydliště: Kladno

#7 Příspěvek od Mendor »

Zde je popsán princip komunikace I2C mezi MCU a EEPROM, ten nesouvisí s velikostí paměti.

tmm

#8 Příspěvek od tmm »

Atlan: Díky moc, už to pracuje jak má :) Chyba byla hlavnì zde:

Kód: Vybrat vše

MOVLW   B'1010000'
Chybìla ještì jedna nula na konci :O

Odpory byly všude správnì, kontrolovali sme to osciloskopem

Ještì jednou dík :)

Doladím kód a pak to sem celý hodím pro ostatní zájemce :)

Uživatelský avatar
Atlan
Příspěvky: 4499
Registrován: 10 kvě 2004, 02:00
Bydliště: Košice

#9 Příspěvek od Atlan »

no ..stava sa .....:) trivialnost isa nekontroluju co uz ...:) hlavne ze to beha :D

Uživatelský avatar
vilem
Příspěvky: 13
Registrován: 11 pro 2008, 01:00

#10 Příspěvek od vilem »

tmm píše:Atlan: Díky moc, už to pracuje jak má :) Chyba byla hlavně zde:

Kód: Vybrat vše

MOVLW   B'1010000'
Chyběla ještě jedna nula na konci :O

Odpory byly všude správně, kontrolovali sme to osciloskopem

Ještě jednou dík :)

Doladím kód a pak to sem celý hodím pro ostatní zájemce :)
Ahoj mohl by jsi sem dát nebo mi poslat zdrojak na to I2C,neboť taky řeším podobný problém s pamětmi a nevím si s tím moc rady. Díky

tmm

#11 Příspěvek od tmm »

Tady sem ti vytáhnul svùj kód - není dokonalý, hlavnì co se týèe èasování, urèitì by to šlo zrychlit - ale nechce se mi s tím už drbat ;)
Přílohy
i2c.txt
(5.82 KiB) Staženo 198 x

Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“