;файл I2С.рrg
;Процедуры чтения и записи по интерфейсу I2C
;+----------- порт D ---------+
.equ pSCL = 4
.equ pSDA = 6
;-------------------------------
.def DATA = r17
.def ClkA = r18
.def cnt = r23
.def AddrL = r24 ;адреса EEPROM
.def AddrH = r25
;---------------- запись EEPROM ------------
WriteFlash: ;в AddrL,AddrH — адрес, данные в DATA
;на выходе если бит с = 1 в регистре флагов, то ошибка
cbi PORTD,pSDA
cbi PORTD,pSCL
ldi cnt,120 ;120 попыток прописать
loop120f:
push DATA
rcall start
ldi DATA,0xA0 ;addr device=0,r/w=0
rcall write
brcs rt_writef ;C=1 ERROR
mov DATA,AddrH ;set HI address
rcall write
brcs rt_writef ;C=1 ERROR
mov DATA,AddrL ;set LO address
rcall write
brcs rt_writef ;C=1 ERROR
pop DATA ;set data to DATA
rcall write
brcs rt_f ;C=1 ERROR
rcall stop
brcs rt_f ;C=1 ERROR
ret
;--------------- чтение EEPROM -------------
ReadFlash: ;в AddrL,AddrH — адрес, данные в DATA
;если бит с = 1 в регистре флагов, то ошибка
cbi PORTD,pSDA
cbi PORTD,pSCL
ldi cnt,120
loop_read_f:
rcall start
ldi DATA,0xA0 ;addr device=0,r/w=0
rcall write
brcs rt__f ;C=1 ERROR
mov DATA,AddrH ;set HI address
rcall write
brcs rt__f ;C=1 ERROR
mov DATA,AddrL ;set LO address rcall write
brcs rt__f ;C=1 ERROR
rcall start
ldi DATA,0xA1 ;addr device=0,r/w=1
rcall write
brcs rt__f ;C=1 ERROR
clt; ;no put ACK
rcall read
rcall stop
brcs rt__f ;G=1 ERROR
ret
rt__f:
dec cnt
brne loop_read_f
ret
rt_writef:
pop DATA
rt_f:
brcc Ok_wr_f
dec cnt
brne loop120f
Ok_wr_f:
ret
;------------ запись RTC ------------
write_i2c: ;b ClkA — адрес, данные в DATA
;если бит с = 1 в регистре флагов, то ошибка
cbi PORTD,pSDA
cbi PORTD,pSCL
ldi cnt,120 ;120 попыток прописать
lоор120:
push DATA
rcall start
ldi DATA,0bi1010000 ;addr device,r/w=0
rcall write
brcs rt_write ;C=1 ERROR
mov DATA,ClkA ;set HI address
rcall write
brcs rt_write ;C=1 ERROR
pop DATA ;set data to DATA
rcall write
brcs rt_ ;C=1 ERROR
rcall stop
brcs rt_ ;C=1 ERROR
ret
;-----------чтение RTC-----------
read_i2c: ;ClkA — адрес, данные в DATA
;если бит с = 1 в регистре флагов, то ошибка
cbi PORTD,pSDA
cbi PORTD,pSCL
ldi cnt,120
loop_read_:
rcall start
ldi DATA 0b11010000 ;addr device,r/w=0
rcall write ;C=1 ERROR
mov DATA ClkA ;set HI address
rcall write
brcs rt ;C=1 ERROR
rcall stare
ldi DATA, 0b11010001 ;addr device, r/w=1
rcall write
brcs rt ;C=1 ERROR
clt ;no put ACK
rcall read
rcall stop
brcs rt ;C=1 ERROR
ret
rt__:
dec cnt
brne loop_read_
ret
rt_write:
pop DATA
rt_:
brcc Ok_wr_
dec cnt
brne loop120
Ok_wr_:
ret
;--------------------------------
write: ;запись байта из DATA
push DATA
push cnt
ldi cnt,8 ;счетчик бит
x42:
rol DATA
brcs sei
sbi DDRD,pSDA
rjmp del_wr
sel:
cbi DDRD,pSDA
del_wr:
cbi DDRD,pSCL
rcall delay
sbi DDRD,pSCL
rcall delay
dec cnt
brne x42 ;следующий бит
cbi DDRD,pSDA ;освободить pSDA для АСК
rcall delay
cbi DDRD,pSCL
rcall delay
clc
sbic PIND,pSDA ;читаем в бит С состояние АСК
sec ;АСК не пришел
sbi DDRD,pSCL
rcall delay
pop cnt
pop DATA
ret
read: ;чтение в DATA, бит t=1 —> ответить АСК, t=0 не отвечать АСК
ldi DATA,1
loop_read:
sbi DDRD,pSCL ;SCL=0
cbi DDRD,pSDA ;SDA=1
rcall delay
cbi DDRD,pSCL ;SCL=1
rcall delay
clc
sbic PIND,pSDA ;читать SDA в бит С
sec
rol DATA
brcc loop_read
;отсылаем ACK ()
sbi DDRD,pSCL ;SCL=0
rcall delay
brts se0
cbi DDRD,pSDA ;не отвечать ACK (t), SDA=1
rjmp rd_
se0:
sbi DDRD,pSDA ;отвечать ACK (t), SDA=0
rd_:
clc
rcall delay
cbi DDRD,pSCL ;SCL=1
rcall delay
ret
start:
cbi DDRD,pSDA
cbi DDRD,pSCL
rcall delay
sbis PINC,pSDA
rjmp start
sbis PINC,pSCL
rjmp start
sbi DDRD,pSDA ;0=SDA
rcall delay
sbi DDRD,pSCL ;0=SCL
rcall delay
ret
stop:
sbi DDRD,pSDA
sbi DDRD,pSCL
rcall delay
cbi DDRD,pSCL ;1=SCL
rcall delay
cbi DDRD.pSDA ;1=SDA
rcall delay
clc
sbic PIND,pSDA
ret
sbic PIND,pSCL
ret
sec
ret
delay: ;~5 мкс (кварц 4 МГц)
push cnt
ldi cnt,6
cyk_delay: dec cnt
brne cyk_delay
pop cnt
ret