ldi СlкА,0 ;адрес регистра секунд
rcall read_i2c ;в data значение регистра секунд
brcs stopW
ret
Записав все эти процедуры в любом месте программы (но поблизости друг от друга, чтобы обеспечить беспроблемный переход на метку stopw), мы включаем в процедуру начального запуска такой фрагмент (листинг 16.13).
Листинг 16.13
;======инициализация часов =======
rcall ReadSet ;прочли установочные байты
;в temp регистр установок, в data секунды
cpi DATA,$80 ;если больше или равно 128
brsh setsek ;то завести часы
cpi temp,$10 ;если выход не установлен
brne st_clk ;тогда только его установка
rjmp setRAM
setsek:
clr temp
rcall IniSek ;устанавливаем секунды = 0
st_clk:
rcall IniClk ;установка выхода
setRAM:
rcall Rclocklni ;в любом случае чтение часов в память
...
Значение $10 регистр установок должен иметь, если мы ранее уже устанавливали часы. Процедура чтения значений часов RclockIniв память у нас отсутствует, и мы поспешим исправить это, включив в текст туда же, где находятся остальные процедуры для часов, еще две: ReadClkдля чтения BCD-значений и RclockIni для преобразования их в распакованный формат (листинг 16.14). Предварительно зададим место в SRAM, куда мы будем складывать значения всех разрядов времени (включая календарь), и отдельно только часы и минуты, но распакованные (они могут пригодиться для индикации).
Листинг 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
Читать дальше
Конец ознакомительного отрывка
Купить книгу