Листинг 16.14
;SRAM старший байт адреса SRAM=0x01
.equ Sek = 0x10 ;текущие секунды BCD-значение
.equ Min = 0x11 ;текущие минуты
.equ Hour = 0x12 ;текущие часы
.equ Date = 0x13 ;текущая дата
.equ Month = 0x14 ;текущий месяц
.equ Year = 0x15 ;текущий год
;распакованные часы
.equ DdH = 0x16 ;часы старш. дес.
.equ DeH = 0x17 ;часы младший дес.
.equ DdM = 0x18 ;мин старш. дес.
.equ DeM = 0x19 ;мин младш. дес.
;<начиная с адреса $20 у нас хранятся коэффициенты>
…
Rciockini: ;инициализация часов
rcall ReadClk ;сложили часы в память
ldi ZH,0x01;
ldi ZL,Sek ;адрес секунд в памяти
ld temp,Z ;извлекаем из памяти упакованные Sek
mov count_sek,temp
andi temp,0b11110000 ;распаковываем — старший
swap temp ;старший в младшей тетраде
ldi data,10
mov mult10,data ;в mult10 всегда будет 10
mul temp,mult10 ;умножаем на 10 в r1:r0 результат умножения
andi count_sek,0b00001111 ;младший
add count_sek,r0 ;получили hex-секунды
ldi ZL,Hour ;распакованные в память
ld temp,Z
mov data,temp
andi temp,0b00001111 ;младший часов
ldi ZL,DeH
st Z,temp
andi data, 0b11110000 ;старший часов
swap data ;старший в младшей тетраде
ldi ZL,DdH
st Z,data
ldi ZL,Min ;распакованные в память
ld temp,Z
mov data,temp
andi temp,0b00001111 ; младший минут
ldi ZL,DeM
st Z,temp
andi data,0b11110000 ;старший минут
swap data ;старший в младшей тетраде
ldi ZL,DdM
st Z,data
ret
ReadClk: ;чтение часов
ldi ZH,1 ;старший RAM
ldi ZL,Sek ;адрес секунд в памяти
ldi ClkA,0 ;адрес секунд в часах
sbis PinC,pSDA
rcall err_i2c
rcall start
ldi DATA,0b11010000 ;I2С-адрес часов+запись
rcall write
brcs stopR ;C=1 если ошибка
mov DATA,ClkA ;адрес регистра секунд
rcall write
brcs stopR ;С=1 если ошибка
rcall start
ldi DATA,0b11010001 ; адрес часов+чтение
rcall write
brcs stopR ;C=1 если ошибка
set;CK
rcall read ;читаем секунды
brcs stopR ;C=1 если ошибка
st Z +,DATA ;записываем секунды в память
rcall read ;читаем минуты
brcs stopR ;С=1 если ошибка
st Z+,DATA ;записываем минуты
rcall read ;читаем часы
brcs stopR ;С=1 если ошибка
st Z +,DATA ;пишем часы в память
rcall read ;день недели читаем, но никуда не пишем
brcs stopR ;С=1 если ошибка
rcall read ;дата — читаем
brcs stopR ; С=1 если ошибка
st Z +,DATA ;дату записываем
rcall read ;месяц читаем
brcs stopR ;С=1 если ошибка
st Z+,DATA ;месяц записываем
clt ;НЕ давать АСК — конец чтения
rcall read ;год читаем
brcs stopR ;С=1 если ошибка
st Z+,DATA ;год записываем
rcall stop
ret
stopR:
ldi temp,$EE ;подтверждение не получено
rcall out_com
ret