Прерывание по переполнению Timer 0 для управления разрядами происходит независимо от прерывания Timer 1 и использует установленные в последнем значения часов. По Timer 0 обнуляются все выходы всех портов, управляющие индикацией, затем проверяется значение счетчика POS, отсчитывающего последовательные номера разрядов (от 0 до 3). Чтобы не тратить время на всякие проверки и обнуления, для организации счетчика до четырех здесь учитывается тот факт, что число 4 совпадает с числом комбинаций первых двух бит. Тогда для последовательного непрерывного счета (0–1-2-3–0–1…) достаточно каждый раз увеличивать счетчик на единицу (см. команду inc posв конце процедуры), а в начале ее лишь обнулять старшие шесть бит (команда andi pos, 3). Далее в зависимости от значения счетчика ( cpi POS….) устанавливаем питание нужного индикатора ( sbi PortD,)и вызываем процедуру установки маски сегментов SET_SEG, причем устанавливаемая маска определяется значением данного разряда в часах.
В процедуре SEG_SETи собственно процедурах установки маски ( OUT_х) я предлагаю вам разобраться самостоятельно. Единственный вопрос, который у вас здесь может возникнуть— почему не применить удобный способ непосредственного задания маски рисунков цифр через загрузку констант командой lpm, как я писал в главе 13 — вместо многочисленных «тупых» процедур отдельно для каждой цифры? Дело в том, что маску удобно использовать, если у вас выводы управления разрядами идут подряд (к примеру, когда биты PortD 0–7 соответствуют битам маски 0–7). Тогда маску достаточно «приложить» к регистру порта, и программа резко сокращается. А здесь это сделать нельзя, т. к. «перестраивание» маски под выводы различных портов займет не меньше места, чем простая и понятная прямая установка выводов.
Процедура установки часов работает следующим образом. При коротком нажатии на Кн1 возникает прерывание INT1 (процедура по метке INTT1), в котором первым делом проверяется, есть ли сетевое питание (бит 1 регистра Flag, см. далее), иначе и сама установка не требуется. Далее, как обычно, запрещается само прерывание INT1 во избежание дребезга. Разрешается оно в прерывании Timer 1 (см. начало текста процедуры TIM1), которое, как мы уже знаем, происходит каждую секунду. Таким образом время нечувствительности, в течение которого можно отпустить кнопку без последствий (без перескока на произвольный разряд), составляет случайную величину от 0 до 1 с. На самом это не совсем верное решение, и сделано так только для простоты — следовало бы пропустить одну секунду, и только потом разрешать, иначе вероятность дребезга все-таки остается большой.
Далее в прерывании INT1 устанавливается отдельный счетчик разрядов set_up, который будет считать от 1 до 4 (если он больше, то выходим из режима установки), и признак режима установки (бит 0 регистра Flag). Если этот признак установлен, то разряд, соответствующий установленному номеру в счетчике set_up, будет мигать. Это достигается с помощью вспомогательного счетчика count(см. процедуру TIM1по метке CONT_1). В этом же месте программы отслеживается состояние Кн2: если она нажата и удерживается, то каждую секунду происходит увеличение значения выбранного разряда на единицу, в тех пределах, в которых это допускается (для единиц минут — от 0 до 9, для десятков минут — от 0 до 5, для десятков часов — от 0 до 2, причем предел единиц часов зависит от значения десятков), далее значение опять обращается в ноль. Отпустив кнопку Кн2, вы фиксируете установленное значение, а нажав кратковременно на Кн1, переходите к следующему разряду. После прохождения всех разрядов, при последнем (пятом) нажатии Кн1, режим установки отменяется, т. е. бит 0 регистра Flagсбрасывается (см. процедуру по прерыванию INT1).
Немаловажная особенность этой конструкции — то, что во время установки счет времени прекращается (команды rjmp END_TIM1в процедуре TIM1, это было сделано по неопытности, на самом деле там можно было поставить просто reti, но для наглядности я ничего менять не стал), а при выходе из режима установки счетчик секунд устанавливается в состояние 59 (команда ldi sek, 59), т. е. счет сразу же начинается с новой минуты. Окончание установки — довольно важный момент, который можно организовать по-разному, но данный способ самый удобный, т. к. вам достаточно дождаться окончания текущей минуты по образцовым часам, и в этот момент сделать последнее нажатие, выйдя из режима установки, чтобы довольно точно синхронизировать время. Сравните, например, как неудачно выполнена ручная установка часов в Windows, где часы продолжают идти и во время установки. А если бы мы обнуляли счетчик секунд, вместо его установки в максимальное значение, то нам пришлось каждый раз устанавливать число минут на единицу большее, что неудобно.
Читать дальше
Конец ознакомительного отрывка
Купить книгу