Dobrze realizuję I2C. Błąd leżał w procedurze odczytu. I jak się okazało nieświadomie naprowadzałem Cię na błąd - w liczniku pętli powinno być 7 :) i oprócz tego naprawiłem jeszcze jeden błąd. Zamieszczam w 100% sprawdzone procedury do obsługi magistrali I2C ASM mojego autorstwa.
;==========================================================
;Procedury obs³ugi magistrali I2C ASM.
;Pawe³ Ko³odziej, 2010r
;pawel_361@op.pl
;==========================================================
;konfiguracja
.INCLUDE " m8def.inc "
.equ i2cport =portd ;zmieñ ostatni¹ literê na literê portu, na jakim pracuje i2c
.equ i2cddr =ddrd ;zmieñ ostatni¹ literê na literê portu, na jakim pracuje i2c
.equ i2cpin =pind ;zmieñ ostatni¹ literê na literê portu, na jakim pracuje i2c
.equ sda =1 ;wpisz na jakiej linii portu jest linia sda
.equ scl=2 ;wpisz na jakiej linii portu jest linia scl
.def licznik =r21 ;okrel jaki rejestr bedzie wykorzystywany jako licznik
;r20 to rejest do którego zapisany zostaje odczytany z I2C bajt i równie¿ z niego odczytywany jest bit, który ma byæ wys³any na magistralê I2C
;Na koñcu programu umieszczony jest podprogram I2CDELAY generuj¹cy opónienie rzêdu 100uS przy kwarcu 1MHz. Przy innych czêstotliwociach trzeba go skorygowaæ.
;==========================================================
I2cstart:
;==========================================================
SBI I2CDDR,SCL ;SCL jako wyj
SBI I2CDDR,SDA ;SDA jako wyj
SBI I2CPORT,SCL ;SCL stan wysoki
SBI I2CPORT,SDA ;SDA stan wysoki
RCALL I2CDELAY ;OPÓNIENIE
CBI I2CPORT,SDA ;SDA stan niski /procedura start
RCALL I2CDELAY ;OPÓNIENIE
CBI I2CPORT,SCL ;SCL stan niski
RCALL I2CDELAY ;OPÓNIENIE
RET
;==========================================================
I2cstop:
;==========================================================
SBI I2CDDR,SCL ;SCL jako wyj
SBI I2CDDR,SDA ;SDA jako wyj
CBI I2CPORT,SDA ;stan niski SDA
RCALL I2CDELAY ;OPÓNIENIE
SBI I2CPORT,SCL ;stan wysoki SCL
RCALL I2CDELAY ;OPÓNIENIE
SBI I2CPORT,SDA ;stan wysoki SDA
RCALL I2CDELAY ;OPÓNIENIE
RET
;==========================================================
i2cwrite: ;PROCEDURA ZAPISU BAJTU NA LINIÊ I2C
;==========================================================
SBI I2CDDR, SDA ;SDA jako wyjcie
ldi licznik, 8 ;petla zapisu zostanie powtórzona 8 razy
loop:
sbrs r20, 7 ;jeli bit 7 rejestru r20 jest 1, to omiñ nastêpny rozkaz
CBI I2CPORT, SDA ;ustaw na SDA stan niski
sbrc r20, 7 ;jeli bit 7 rejestru r20 jest 0, to omiñ nastêpny rozkaz
SBI I2CPORT, SDA ;ustaw na SDA stan wysoki
RCALL I2CDELAY ;OPÓNIENIE
SBI I2CPORT, SCL ;ustaw na SCL stan wysoki, ZBOCZE NARASTAJ¥CE
RCALL I2CDELAY ;opónienie
lsl r20 ;przesuniêcie w lewo r20
CBI I2CPORT, SCL ;zejdz z zegarem
RCALL I2CDELAY ;OPÓNIENIE
dec licznik ;dekrementacja licznika
brne loop ;jeli licznik nie jest pusty, to ponownie wykonaj petle lop
; ACK
CBI I2CDDR, SDA ;SDA jako wejcie
CBI I2CPORT, SDA ;ustaw na SDA stan NISKI
RCALL I2CDELAY ;OPÓNIENIE
SBI I2CPORT, SCL ;ustaw na SCL stan wysoki
RCALL I2CDELAY ;OPÓNIENIE
CBI I2CPORT, SCL ;ustaw na SCL stan NISKI
RCALL I2CDELAY ;OPÓNIENIE
RET
;==========================================================
i2cread: ; procedura odczytu bajtu z szyny I2C
;==========================================================
ldi r20,0b00000000 ; wyczysc komórke do której zostan¹ zapisane odczytane bity
CBI I2CDDR, SDA ; SDA jako wejcie
CBI I2CPORT, SDA ; ustawienie stanu NISKIEGO na SDA
RCALL I2CDELAY ; OPÓNIENIE
ldi licznik, 7 ; pêtla loop1 bedzie powtózona 7 razy
loop1:
SBI I2CPORT, SCL ; stan wysoki na SCL
RCALL I2CDELAY ; opónienie
SBIc I2CPIN, SDA ; jeli SDA jest w stanie niskim to pomiñ nastêpn¹ instrukcjê
ori r20,0b00000001 ; ustaw bit 0 r20
lsl r20 ; przesuniêcie r20 w lewo
CBI I2CPORT, SCL ; stan niski na SCL
RCALL I2CDELAY
dec licznik ; zmniejsz licznik pêtli o 1
brne loop1 ; jeli niezerowy to skocz do petla2
SBIc I2CPIN, SDA ; jeli SDA jest w stanie niskim to pomiñ nastêpn¹ instrukcjê
ori r20,0b00000001 ; ustaw bit 0 r20
; ACK
SBI I2CDDR, SDA ; SDA jako wyjcie
RCALL I2CDELAY
CBI I2CPORT, SDA ; ustaw na SDA stan niski (ACK)
RCALL I2CDELAY
SBI I2CPORT, SCL ; ustaw na SCL stan wysoki
RCALL I2CDELAY ; opónienie
CBI I2CPORT, SCL ; ustaw na SCL stan niski
RCALL I2CDELAY
RET
;==========================================================
I2CDELAY: ; Podprogram generuj¹cy opónienie rzêdu 100uS przy kwarcu 1MHz.
;==========================================================
ldi R17, $21
E0: dec R17
brne E0
RET