projekt
Guest
Wed Aug 30, 2006 8:03 pm
Mam M41T00 (i2c) podpiety do Atmega128 i chcialbym z niego odczytac
wszystkie 8 rejestrow za jednym zamachem. W dokumentacji do M41T00 napisali,
ze jest to mozliwe, wedlug schematu:
START
adres RTC (czyli D0) R/W=0
ACK
Adres pierwszego rejestru do odczytania
ACK
START
adres RTC (czyli D0) R/W=1
ACK
Dane z pierwszego rejestru
ACK
Dane z kilejnego rejestru
ACK
Dane z klejnego rejestru
ACK
itd...
Niestety udaje mi sie poprawnie odczytac tylko pierwszy rejestr, potem
odbieram tylko $FF mimo ze kolejne rejestry zawieraja inne dane, jesli je
czytac osobno.
Ponizej zamieszczam procki w asm. I2C_Read dziala dobrze, a I2C_Read_Word
odczytuje poprawnie tylko pierwszy bajt.
Program puszczam pod emulatorem JTAGICE wiec mam podglad na biezaco.
Macie moze jakies sugestie? Co zmienic, zeby zadzialalo? Bardzo podobnie
odczytuje sie pamieci 24LC16 i pokrewne, moze z nimi macie doswiadczenie.
Pozdrawiam.
/PM
..macro WAIT
wait1:
LDS tmp,TWCR
sbrs tmp,TWINT
rjmp wait1
..endmacro
;*********************************************************************
..macro START
ldi tmp,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);send START
STS TWCR,tmp
..endmacro
;*********************************************************************
..macro STOP
ldi tmp,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN) ;send STOP
STS TWCR,tmp
..endmacro
;*********************************************************************
I2C_Setup:
LDI tmp,10 ;szybkosc 28KHz przy zegarze 1MHz
STS TWBR,tmp
LDI tmp,(0<<TWPS1)|(0<<TWPS0)
STS TWSR,tmp
RET
;*********************************************************************
; WYWOŁANIE:
; tmp=adres do odczytania
; ZWRACA:
; tmp=odczytany bajt
I2C_Read:
^^^^^^^^ ta procka dziala OK bo odczytuje tylko jeden bajt
push tmp ;zapamietuje adres do odczytania
START
WAIT
ldi tmp,(ADDRRTC|SDA_W) ;send RTC Address
STS TWDR,tmp
ldi tmp,(1<<TWINT)|(1<<TWEN)
STS TWCR,tmp
WAIT
pop tmp ;przywracam adres do odczytania
STS TWDR,tmp ;send Word Address
ldi tmp,(1<<TWINT)|(1<<TWEN)
STS TWCR,tmp
WAIT
START
WAIT
ldi tmp,(ADDRRTC|SDA_R) ;send RTC Address
STS TWDR,tmp
ldi tmp,(1<<TWINT)|(1<<TWEN)
STS TWCR,tmp
WAIT
ldi tmp,(1<<TWINT)|(1<<TWEN)
STS TWCR,tmp
WAIT
STOP
LDS tmp,TWDR ;bajt odczytany
ret
;*********************************************************************
; WYWOŁANIE:
; tmp=adres do odczytania
; ZWRACA:
; tmp=1 bajt
; tmp2=2 bajt
I2C_Read_Word:
^^^^^^^^^^^^^ ta procka odczytuje poprawnie pierwszy bajt a w drugim zwraca
$FF(a nie powinna)
push tmp
START
WAIT
ldi tmp,(ADDRRTC|SDA_W) ;send RTC Address
STS TWDR,tmp
ldi tmp,(1<<TWINT)|(1<<TWEN)
STS TWCR,tmp
WAIT
pop tmp
STS TWDR,tmp ;send Word Address
ldi tmp,(1<<TWINT)|(1<<TWEN)
STS TWCR,tmp
WAIT
START
WAIT
ldi tmp,(ADDRRTC|SDA_R) ;send RTC Address
STS TWDR,tmp
ldi tmp,(1<<TWINT)|(1<<TWEN)
STS TWCR,tmp
WAIT
ldi tmp,(1<<TWINT)|(1<<TWEN)
STS TWCR,tmp
WAIT
LDS tmp,TWDR ;1 bajt odczytany
push tmp
ldi tmp,(1<<TWINT)|(1<<TWEN)
STS TWCR,tmp
WAIT
STOP
LDS tmp2,TWDR ;2 bajt odczytany
pop tmp
ret
projekt
Guest
Wed Aug 30, 2006 8:26 pm
Odpowiem sobie sam, bo znalazlem rozwiazanie. Atmaga musi wyslac sygnal ACK
po odebraniu kazdego bajtu, czyli trzeba ustawic bit TWEA w TWCR. Inaczej
RTC mysli, ze nie chcemy od niego kolejnych bajtow danych i konczy
transmisje. Poprawiona procka jest ponizej.
Pozdrawiam
/PM
PS: moze komus sie to przyda ;)
I2C_Read_Word:
push tmp
START
WAIT
ldi tmp,(ADDRRTC|SDA_W) ;send RTC Address
STS TWDR,tmp
ldi tmp,(1<<TWINT)|(1<<TWEN)
STS TWCR,tmp
WAIT
pop tmp
STS TWDR,tmp ;send Word Address
ldi tmp,(1<<TWINT)|(1<<TWEN)
STS TWCR,tmp
WAIT
START
WAIT
ldi tmp,(ADDRRTC|SDA_R) ;send RTC Address
STS TWDR,tmp
ldi tmp,(1<<TWINT)|(1<<TWEN)
STS TWCR,tmp
WAIT
ldi tmp,(1<<TWINT)|(1<<TWEN|1<<TWEA) ;<to wlasnie ta linijka zostala
poprawiona
STS TWCR,tmp
WAIT
LDS tmp,TWDR ;bajt odczytany
push tmp
ldi tmp,(1<<TWINT)|(1<<TWEN)
STS TWCR,tmp
WAIT
STOP
LDS tmp2,TWDR ;bajt odczytany
pop tmp
ret