Таймер без прерываний
Давайте теперь заставим наш МК управлять этим светодиодом так, чтобы он мигал с частотой примерно один раз в секунду из красного в зеленый. И сначала сделаем это самым простым способом – так, как это делали в те времена, когда микропроцессоры еще не были микроконтроллерами и не содержали никаких дополнительных узлов вроде таймеров. Для отсчета времени тогда пользовались тем фактом, что команды выполняются строго определенное время. Причем в AVR этот способ применять особенно удобно, поскольку большинство команд занимают один такт, за исключением команд передачи управления. Этим способом часто пользуются и по сей день для отсчета программных задержек (не станешь же заводить таймер по каждому случаю), потому урок окажется не совсем бесполезным. Заодно познакомимся с понятием процедур (подпрограмм) и с самими командами передачи управления.
Не вникая в подробности, сразу напишем «правильную» процедуру, позволяющую формировать заданные задержки без таймера. Назовем ее Delay , тогда она запишется так:
Здесь Razr0‑Razr2 – рабочие регистры. Отведем для них регистры r17, r18 и r19 . В начало программы тогда следует внести их определения через команду def (по образцу .def Razr0 = r17 ). Delay с двоеточием – метка, в данном случае обозначающая начало процедуры, команда ret – выход из процедуры (зачем она нужна, пояснено далее). Команда subi вычитает из регистра константу, в данном случае единицу. А команды sbci работают хитрее – они также вычитают константу, но с учетом переноса. Если переноса нет, то они просто ничего не делают (ибо вычитаемое значение равно нулю). Перенос же возникает тогда, когда в результате предыдущей команды вычиталась единица из нуля. Тогда значение регистра меняется с нулевого на все единицы (255), а перенос записывается в специальный бит переноса и учитывается следующей командой sbci . В этой схеме легко узнать принцип работы соединенных между собой двоичных счетчиков из главы 16 , в которых выход старшего разряда предыдущего счетчика соединен со входом переноса следующего. В данном случае счетчик состоит из трех отдельных байтовых регистров, т. е. всего имеет 24 двоичных разряда.
Нам не надо, чтобы счет продолжался до бесконечности, и для этой цели служит команда brcc , которая относится к группе команд передачи управления (branch ) и работает по очень простому правилу – если в момент ее исполнения бит переноса (он обозначается буквой С , от слова саnу , что и значит «перенос») равен нулю (clear , т. е. очищен), то далее выполняется возврат к команде по метке Delay . To есть название команды (brcc ) расшифровывается так: branch if carry clear (перейти, если перенос очищен). В противном случае управление передается на следующую команду – выхода из процедуры ret , счет заканчивается.
Легко сообразить, что в момент выполнения команды brcc перенос станет равен единице только тогда, когда все регистры в предыдущем такте были равны нулю. Поэтому вся процедура работает так: перед ее началом в счетчики Razr0‑Razr2 записывается некое заданное число, которое в каждом такте уменьшается на единицу, и вся процедура заканчивается при достижении нулевого значения во всех разрядах. Отсюда, зная тактовую частоту МК и время выполнения команд (по такту на вычитание и два такта на возврат к начальной метке), легко вывести формулу: записываемое в счетчики число N , соответствующее нужному интервалу времени T (с) при тактовой частоте F (Гц), рассчитывается, как T ·F /(M + 2), где М – число регистров‑счетчиков, в данном случае 3.
Число N в данном случае трехбайтовое. Старший байт записывается в Razr2 , младший – в Razr0 . При тактовой частоте 4 МГц мы можем получить задержку до 4,19 с, если запишем в регистры все единицы: число 16 777 215 = $FFFFFF. Если же нам требуется, например, задержка в 1 секунду, то придется записать число 800 000 или $0С3500, если в полсекунды – число 400 000 или $061А80.
Вооружившись этими знаниями, попробуем соорудить программу мигалки. Сначала давайте определимся с алгоритмом переключения из красного в зеленый. Наиболее универсальный метод здесь такой: каждый раз будем определять, в каком состоянии в данный момент находится светодиод (по состоянию какого‑нибудь из задействованных выводов порта), и переключать его в противоположное. Это может выглядеть таким образом:
Не углубляясь в подробности, заметим, что такой алгоритм (он, конечно, не единственно возможный) будет устойчив к начальным условиям – в каком бы состоянии к моменту его начала ни находились биты 5 и 6 (даже если светодиод был совсем погашен), максимум через один цикл они придут в противоположное состояние, и мигание начнется. Теперь осталось соединить все это в законченную программу – повторять процедуру мигания через промежуток времени, определяемый процедурой Delay . Программа будет выглядеть таким образом:
О назначении первых двух операторов программы мы поговорим позднее. Rcall – команда вызова процедуры (в данном случае Delay ). После этой команды всегда должна где‑то встретиться команда ret (возврата из процедуры), иначе программа к основной последовательности операторов вернуться не «сумеет». Сама программа представляет собой бесконечный цикл, т. к. заканчивается оператором безусловного перехода обратно в начало (rjmp Migbegin ). В данном случае мигание будет происходить с периодом в секунду (полсекунды красный, полсекунды зеленый), для другого периода нужно изменить записываемое в счетчики значение. Программа может служить хорошей основой для любимого развлечения радиолюбителей – конструирования елочных гирлянд.
* * *
Заметки на полях
Кстати, о елочных гирляндах. На мой вкус, самый приличный вариант построения такой гирлянды, который к тому же не встретишь в продаже, – это обеспечить вместо раздражающего мигания медленное изменение из одного цвета в другой. Его несложно построить, используя явление биений : если сложить два почти совпадающих по частоте колебания через элемент, например, «Исключающее ИЛИ», то на выходе возникнет колебание с меняющейся скважностью (см. рис. 15.8, а , аналогичный эффект можно получить и с другими логическими функциями). Если напряжение такой формы подать на лампочку, то высокочастотные составляющие не будут заметны, и лампочка станет медленно зажигаться и гаснуть. При очень близких, но все‑таки не равных частотах, период биений может составить минуты, а если взять две разноцветных лампочки или светодиода и включить их в противофазе, то гирлянда начнет медленно менять цвет с одного на другой. Причем в качестве одной из частот удобно взять частоту электрической сети, которая никогда точно не равна 50 Гц.
Для осуществления этого проекта на дискетной логике пришлось бы городить довольно громоздкую схему на счетчиках с предзагрузкой, причем долго подгонять коэффициент деления так, чтобы смена цветов не была слишком быстрой. А вот с помощью контроллера такая задача решается, что называется, в пять секунд. Для одной лампочки или светодиода почти не нужно даже менять схему по сравнению с рис. 19.2 – достаточно подключить светоизлучающий элемент не непосредственно к выводу контроллера, а через ключевой транзистор. Коллекторную цепь его, в которую и будет включена лампочка или светодиод, при этом нужно питать от источника пульсирующего напряжения с частотой сети (от отдельной обмотки трансформатора через один диод, без сглаживания). А частоту на выводе МК, управляющую открыванием транзистора, подогнать примерно под 50 Гц (т. е. длительность задержки должна составить примерно 0,01 с, для чего в счетчики придется записать число около 8000, или, в шестнадцатеричной системе, 1F40h – как видите, можно сократить число регистров задержки до двух). Частоты станут складываться прямо на транзисторе – лампочка будет гореть только тогда, когда и на коллекторе, и на его базе одновременно присутствует высокий уровень напряжения. Чтобы сделать эффект более заметным, можно поиграть со значением скважности, т. е. ввести разные задержки для красного и зеленого состояний. Поскольку у нас уже имеется два управляемых в противофазе вывода, можно добиться переливания из одного цвета в другой, а если усложнить программу, подключив еще несколько выводов МК, то можно получить весьма сложные и красивые эффекты. И, что приятно, экспериментируя с такой схемой, почти не придется браться за паяльник.
Дата добавления: 2016-05-11; просмотров: 1037;