Делаю устройство, в котором помимо всего должен быть учет времени с календарём. Алгоритм не сложен, выдернул его из своего старого проекта часов, но есть одна проблема: должен он выполняться в прерывании (1 сек по таймеру), при этом должен выполняться как можно быстрее, т.к. блокирует другие прерывания, которые очень не желательно прозевать.
Этот велосипед изобрёл сам, поэтому может кто подскажет более эффективный алгоритм? Собственно код:
Буферы памяти:
Код: Выделить всё
; Буферы часов
clk_hh: .byte 1 ; Часы
clk_mm: .byte 1 ; Минуты
clk_ss: .byte 1 ; Секунды
clk_yyyy: .byte 2 ; Год
clk_mnt: .byte 1 ; Месяц
clk_dd: .byte 1 ; День
clk_dw: .byte 1 ; День недели
Массив количества дней в месяце
Код: Выделить всё
;-------------------------------------------------------------------------------
; Число дней в месяце
;-------------------------------------------------------------------------------
cnt_day: .db 0,31,28,31,30,31,30,31,31,30,31,30,31
Код: Выделить всё
run_clock:
lds r16,clk_ss ; Крутим секунды
inc r16
cpi r16,60
brcc rc_min
sts clk_ss,r16
ret
rc_min: ; Крутим минуты
clr r16
sts clk_ss,r16
lds r16,clk_mm
inc r16
cpi r16,60
brcc rc_hh
sts clk_mm,r16
ret
rc_hh: ; Крутим часы
clr r16
sts clk_mm,r16
lds r16,clk_hh
inc r16
cpi r16,24
brcc rc_dd
sts clk_hh,r16
ret
rc_dd: ; Крутим день и день недели
clr r16
sts clk_hh,r16
lds r16,clk_dw
inc r16 ; День недели
cpi r16,8
brcs rc_dd2
ldi r16,1
rc_dd2:
sts clk_dw,r16
lds r16,clk_dd
lds r17,clk_mnt ; День с учетом количества дней в месяце
ldi2Z cnt_day
add16Z r17
lpm r19,Z
lds r18,clk_yyyy ; Проверим на високосный год
andi r18,0b00000011 ; У него будет два младших бита в нулях
brne rc_dd3
cpi r17,2 ; Если февраль
brne rc_dd3
inc r19 ; Увеличиваем кол-во дней
rc_dd3:
inc r16
cp r19,r16
brcs rc_mnt
sts clk_dd,r16
ret
rc_mnt: ; Крутим месяц
ldi r16,1 ; Он у нас уже есть в r17
sts clk_dd,r16
inc r17
cpi r17,13
brcc rc_yy
sts clk_mnt,r17
ret
rc_yy: ; Крутим год
ldi r17,1
sts clk_mnt,r17
lds r24,clk_yyyy
lds r25,clk_yyyy+1
adiw r24,1
sts clk_yyyy,r24
sts clk_yyyy+1,r25
ret



