Programowy master I2C a PCF8582

To forum jest dla wszystkich pasjonatów wiecznie młodych mikrokontrolerów '51. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
kooliz
-
Posty: 2
Rejestracja: 29 sty 2009, 23:23
Lokalizacja: Katowice

Programowy master I2C a PCF8582

Post autor: kooliz » 29 sty 2009, 23:48

Witam serdecznie wszystkich maniaków pochodnych 8051!
Chyba również jestem maniakiem, gdyż zamiast odpocząć po pracy to siedzę i bawię się tymi czarnymi kosteczkami:)
Mam mały problem i chciałem poprosić was o pomoc.
Zamarzyło mi się napisanie programu w ASM do obsługi układów na szynie I2C. I wszystko fajnie działała ale tylko z portem we/wy pcf8574. Gdy podłączam pod magistralę pamięć 256 bajtową 8582, program opierający się na tych samych procedurach ASM już nie działa. Wygląda na to że nie odbiera żadnych bitów ACK z układu pamięci.
Próbowałem różne czasy opóźnień i kilka takich samych scalaków ale nic nie pomaga.
Może jest jakiś kruczek o którym nic nie wiem....może ktoś z forumowiczów miał podobne problemy.
Oczywiście zamieszczam kod:

Kod: Zaznacz cały

        cseg at 0h

        ljmp start

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

        org 70h

param1:            ds 1
DATA:              ds 1

        cseg at 100h

start:
        lcall serial_init
        lcall testsend
        lcall serial_put_char
        sjmp $

I2C_DELAY:
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        ret

I2C_READ:            ;reading 8 bits from i2c device
    	mov     r1, #08h
        clr     a
        setb    SDA
    _loop0302:
        setb    SCL
        acall   I2C_DELAY
        mov     C, SDA
    	rlc     a
        clr     SCL
        acall   I2C_DELAY
        djnz    r1, _loop0302
        ret

I2C_WRITE:           ;writing 8 bits in to i2c device
    	mov     r1, #08h
    _loop0301:
    	rlc     a
    	mov     SDA,C
        acall   I2C_DELAY
        setb    SCL
        acall   I2C_DELAY
        clr     SCL
        acall   I2C_DELAY
        djnz    r1, _loop0301
        ret

I2C_START:
        setb    SCL
        setb    SDA
        acall   I2C_DELAY
        clr     SDA
        acall   I2C_DELAY
        clr     SCL
        ret

I2C_STOP:
        clr     SDA
        setb    SCL
        acall   I2C_DELAY
        setb    SDA
        acall   I2C_DELAY
        ret

I2C_RESTART:
        setb    SDA
        setb    SCL
        acall   I2C_DELAY
        clr     SDA
        acall   I2C_DELAY
        clr     SCL
        ret

I2C_READ_ACK:
        setb    SDA
        acall   I2C_DELAY
        setb    SCL
        acall   I2C_DELAY
        mov     C, SDA
        mov     a, #0
        rlc     a
        clr     SCL
        acall   I2C_DELAY
        ret        

I2C_WRITE_ACK:
        clr     SDA
        setb    SCL
        acall   I2C_DELAY
        clr     SCL
        acall   I2C_DELAY
        ret       

I2C_WRITE_NAK:
        setb    SDA
        setb    SCL
        acall   I2C_DELAY
        clr     SCL
        acall   I2C_DELAY
        ret       

I2C_EPROM_WRITE_DELAY:
        mov     param1, #255
        acall   std_delay
        ret

testsend:
        ; zapal jeden z LEDów podłączonych na porcie
        acall   I2C_START
        mov     a, #01000000b
        clr     acc.0
        acall   I2C_WRITE
        acall   I2C_READ_ACK
            lcall   serial_put_char
        mov     a, #7Fh
        acall   I2C_WRITE
        acall   I2C_READ_ACK
            lcall   serial_put_char
        acall   I2C_STOP

        ; zapis pamięci
        acall   I2C_START
        mov     a, #10100000b         ;adres ukladu
        acall   I2C_WRITE
        acall   I2C_READ_ACK
            lcall   serial_put_char
        mov     a, #67h         ;adres w pamieci
        acall   I2C_WRITE
        acall   I2C_READ_ACK
            lcall   serial_put_char
        mov     a, #18h         ;wartosc
        acall   I2C_WRITE
        acall   I2C_READ_ACK
            lcall   serial_put_char
        acall   I2C_STOP
        acall   I2C_EPROM_WRITE_DELAY

        ; odczyt pamięci
        acall   I2C_START
        mov     a, #10100000b        ;adres ukladu
        acall   I2C_WRITE
        acall   I2C_READ_ACK
            lcall   serial_put_char
        mov     a, #67h         ;adres w pamieci
        acall   I2C_WRITE
        acall   I2C_READ_ACK
            lcall   serial_put_char
        acall   I2C_RESTART
        mov     a, #10100001b          ;adres ukladu
        acall   I2C_WRITE
        acall   I2C_READ_ACK
            lcall   serial_put_char
        acall   I2C_READ
        acall   I2C_WRITE_NAK
        acall   I2C_STOP        

        mov     DATA, a

        ; zapalenie innego LED'a
        acall   I2C_START
        mov     a, #01000000b
        clr     acc.0
        acall   I2C_WRITE
        acall   I2C_READ_ACK
            lcall   serial_put_char
        mov     a, #7Eh
        acall   I2C_WRITE
        acall   I2C_READ_ACK
            lcall   serial_put_char
        acall   I2C_STOP

        mov     a, DATA

        ret       

        end
Część procedury testsend operująca na expanderze PCF8574 działa prawidłowo.
Procedura serial_put_char jest wykorzystywana do wyświetlania odebranych wartości bitów potwierdzeń oraz odczytane zawartości komórki pamięci. Wysyłana jest zawsze wartość z akumulatora.

Nie wiem już co myśleć. Dostaję oczopląsu patrząc po raz setny na ten sam kod. Może potrzebuje świeżego spojrzenia? Będę bardzo wdzięczny za ewentualną pomoc.

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 30 sty 2009, 15:42

A może zwyczajnie źle podajesz adres układu pamięci. Wtedy ci nic nie odpowie. Porównaj se noty katalogowe obu układów które obsługujesz. No i napisanie w ASM procedur do I2C do prostych i przyjemnych nie należy.

kooliz
-
Posty: 2
Rejestracja: 29 sty 2009, 23:23
Lokalizacja: Katowice

Post autor: kooliz » 31 sty 2009, 20:06

Adres układu też już sprawdzałem...sam nie wiem ile razy.
Według noty adresacja przebiega następująco:

Selection Device code Chip Enable R/W
Bit b7 b6 b5 b4 b3 b2 b1 b0
Device 1 0 1 0 A2 A1 A0 R/W

Wyjscia adresowe mam zwarte do masy więc jakby na to nie patrzeć cały adres urządzenia powinien być 10100000. Pierwszy bit, wiadomo, zmienia się w zależności od rodzaju komendy.

ASM generalnie do łatwych i przyjemnych nie należy:D
Ale ja chyba lubię się czasem pomęczyć.
Najbardziej mnie jednak irytuje to że z ekspanderem portów wszystko działa, a tu taka klapa. Dodatkowo, pocztą idzie już do mnie zegar RTC, przetwornik AD/AC oraz pamięć 1Mb, wieć nie mogę się poddać:)

ODPOWIEDZ