Собственно , выкладывать и нечего , только засорять тему практически одинаковыми кодами. Поэтому я поступил проще - дополнив свой код подробными комментами , что откуда следует и что из этого вытекает . Задачи сделать часы , я собственно перед собой и не ставил . Причина написания кода указана в комментах.
Кстати ув-ый
ploop раз уж форум разделился , может прикрепим темку . Вчера мин 5 искал , судя по часам
Код: Выделить всё
;- Как решить задачку по "быстрому" сделать часы, не используя длительных преобразований из HEX в BCD
;= Вспомним , что BIN, HEX или десятичное число в начале любого счета похожи как две капли воды
;= Максимальное число до которого может посчитать один регистр 255=0хFF. А нам из всего этого
;= числа нужно чуть-чуть ,два раза по 59 и один по 24 или 12.
;= Значит нам надо сделать так , чтобы младшая тетрада регистра считала до 0x0F девять раз
;= или 4 ну хотя бы 2, а старшая 5,2 или 1. Для всего подсчёта часов потребуется 3 регистра
;= и регистр для высчитывания упакованного BCD для секунд минут и часов. Всего один регистр
;= или чуть чуть памяти (см. код ALK)
ldi XL,0xA6 ;+ Вычитая из 0хFF-0x59 получаем константу 0хA6 которую и загружаем
mov XH,XL ;+ в регистры подсчёта секунд и минут
;= Да , конечно нам нужен счётчик , что нить из таймеров и его прерывание
;= Я использовал WDT - быстро и дёшево , но очень не точно. Мой отставал на 5 сек в минуту.
;= Cобственно проверка точности частоты WDT и послужило целью , что-то по быстрому набрасать
;= на имеющейся базе.
sei
;**************************************************
;* MAIN *
;**************************************************
MAIN:
sbrs Flags,fl_Second ; Ждём когда пройдёт секунда
rjmp Main
cbr Flags,1<<fl_Second ; Сбрасываем флажок секунд , чтобы не запутаться
subi XL,-1 ;- Прошла секунда "вычитаем" из 0xA6 единичку, на самом деле
;- прибавляем и чтобы больше не пояснять получаем 0хА7..0xB9 и т.д
brhc INIT_SEC ;- Пока вот эта команда сравнения не скажет - хватит
;- уже , ты 10-ть именно 10-ть раз посчитал секунды и в младшей тетраде уже ноль. Команда SUBI сбросит флаг (H) в регистре SREG на 10 -ой секунде.
;-
SUM:
mov temp1,XL ;- TEMP1 - ИМЕННО ЭТОТ РЕГИСТР ХРАНИТ ДАННЫЕ СРАЗУ В ДЕСЯТИЧНОМ КОДЕ
subi temp1,0xA6 ;- и для преобразования в десятичный вид нам нужно вычесть 0хA6 из выше полученной суммы
rcall OUT_CLOCK ;- запомнить или сразу вывести на экран десятичное число
rjmp MAIN ;- Возвращаемся ? - значит мы ещё не посчитали до 10
INIT_SEC:
tst XL ;- Проверяем , может мы посчитали все 60 секунд
breq ADD_MINUT ;- Да- прибавим минуту
subi XL,-6 ;- Нет - тогда к нулю (помним что младшей тетраде XL у нас 0
rjmp SUM ;- прибавим нужные нам (6) и вернёмся на подсчёт. При этом
;- сбросив младшую тетраду в ноль , процессор автоматом добавит 1 в старшую тетраду и когда мы
;- выведем число на экран то после 9 как и положено будет 10 и счёт до 10 начнётся заново.
ADD_MINUT:
clr temp1 ;- Ну раз уж мы попали сюда, то прошла уже целая минута
;- и регистр XL полностью по нулям. Можно по разному обнулить TEMP1 - это кому как нравится
rcall OUT_CLOCK ;- Конечно отобразить сей момент на экране
LDI XL,0xA6 ;- И начать считать всё заново
;**************************************************
subi XH,-1
brhc INIT_MINUTs
SUM_MINUTs:
mov temp1,XH ;- Используем тот же самый регистр и для минут , и потом и для часов и т.д
subi temp1,0xA6
rcall OUT_CLOCK
rjmp MAIN
INIT_MINUTs:
tst XH
breq ADD_HOURs
subi XH,-6
rjmp SUM_MINUTs
ADD_HOURs: