IniSek: ;секунды — в temp, если бит 7=1
;то остановить, иначе завести часы
sbis PinC,pSDA ;линия занята
rcall err_i2c
ldi ClkA,0 ;адрес регистра секунд
mov DATA,temp
rcall write_i2c
brcs stopW
ldi temp,$AA ;все отлично
rcall out_com
ret
IniClk: ;установить выход SQW
ldi ClkA,7 ;адрес регистра управления
ldi DATA,0b00010000 ;выход SQW с частотой 1 Гц
rcall write_i2c
brcs stopW
ldi temp,$AA ;все отлично
rcall out_com
ret
stopW:
ldi temp,$ЕЕ ;подтверждение не получено
rcall out_com
ret
err_i2c:
ldi temp,$AE ;линия занята
rcall out_com
sei
ret
Напомню, ЧТО процедура write_i2c (как и использующаяся далее read_i2c) для доступа к часам уже имеется в файле i2c.prg (см.
Раздельные процедуры нам понадобились потому, что иногда часы идут, а выход на прерывание МК у них может оказаться отключенным. Тогда нам надо только его подключить, а время сбивать не следует. А когда вызывать эти процедуры? Прежде всего, при включении контроллера: мы помним, что при самом первом запуске часы следует заводить обязательно. Но могут быть и сбои при перебоях с питанием (на практике бывало так, что выход SQW при работе от батарейки самопроизвольно отключался). Для того чтобы правильно организовать процедуру, нам следует сначала выяснить, в каком состоянии часы находятся (листинг 16.12).
ReadSet:
sbis PinC,pSDA ;линия занята
rcall err_i2c
ldi ClkA,7 ;адрес регистра управления
rcall read_i2c
mov temp,data ;в temp значение регистра управления
ldi СlкА,0 ;адрес регистра секунд
rcall read_i2c ;в data значение регистра секунд
brcs stopW
ret
Записав все эти процедуры в любом месте программы (но поблизости друг от друга, чтобы обеспечить беспроблемный переход на метку stopw), мы включаем в процедуру начального запуска такой фрагмент (листинг 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, куда мы будем складывать значения всех разрядов времени (включая календарь), и отдельно только часы и минуты, но распакованные (они могут пригодиться для индикации).