Таймер без прерываний – программирование для МК

June 27, 2010 by admin Комментировать »

Давайте теперь заставим наш МК управлять этим светодиодом так, чтобы он мигал с частотой примерно один раз в секунду из красного в зеленый. И сна­чала сделаем это самым простым способом: так, как это делали в те времена, когда микропроцессоры еще не были микроконтроллерами и не содержали никаких дополнительных узлов вроде таймеров. Для отсчета времени тогда пользовались тем фактом, что команды выполняются строго определенное время. Причем в AVR этот способ применять особенно удобно, так как большинство команд занимают один такт, за исключением команд передачи управления. Этим способом часто пользуются и по сей день для отсчета про­граммных задержек (не станешь же заводить таймер по каждому случаю), потому урок окажется не совсем бесполезным. Заодно познакомимся с поня­тием процедур (подпрограмм) и с самими командами передачи управления.

Не вникая в подробности, сразу напишем «правильную» процедуру, позво­ляющую формировать заданные задержки без таймера. Назовем ее Delay, тогда она запишется так:

Delay:

subi RazrO,l sbci Razrl,0 sbci Razr2,0 brcc Delay ret

Здесь RazrO—^Razr2 — рабочие регистры, pelay с двоеточием— метка, в данном случае обозначающая начало процедуры, команда ret — выход из процедуры (зачем она нужна, пояснено далее). Команда subi вычитает из регистра константу, в данном случае единицу. А команды sbci работают хитрее: они также вычитают константу, но с учетом переноса. Потому если переноса нет, то они просто ничего не делают (ибо константа равна нулю). Перенос же возникает тогда, когда в результате предыдущей команды вычи­талась единица из нуля. Тогда значение регистра меняется с нулевого на все единицы (255), а перенос записывается в специальный бит переноса и учиты­вается следующей командой sbci. В этой схеме легко узнать принцип работы соединенных между собой двоичных счетчиков из главы 16, в которых выход старшего разряда предыдущего счетчика соединен со входом переноса сле­дующего. В данном случае счетчик состоит из трех отдельных байтовых ре­гистров, то есть всего имеет 24 двоичных разряда.

Нам не надо, чтобы счет продолжался до бесконечности, и для этой цели служит команда Ьгсс, которая относится к группе команд передачи управле­ния (branch) и работает по очень простому правилу: если в момент ее испол­нения бит переноса (он обозначается буквой С, от слова carry, что и значит «перенос») равен нулю (clear, то есть очищен), то далее выполняется возврат к команде по метке Delay. То есть название команды расшифровывается, как branch if carry clear («перейти, если перенос очищен»). В противном случае управление передается на следующую команду — выхода из процедуры ret, счет заканчивается.

Легко сообразить, что в момент выполнения команды Ьгсс перенос будет равен единице только тогда, когда все регистры перед этим были равны ну­лю. Поэтому вся процедура работает так: перед ее началом в счетчики RazrO—Razr2 записывается некое заданное число, которое в каждом такте уменьшается на единицу, и вся процедура заканчивается при достижении ну­левого значения во всех разрядах. Отсюда, зная тактовую частоту МК и вре­мя выполнения команд (по такту на вычитание и два такта на возврат к на­чальной метке), легко вывести формулу: записываемое в счетчики число Л^, соответствующее нужному интервалу времени Т (с) при тактовой частоте F (Гц), рассчитывается, как TF/(M+ 2), где М— число регистров-счетчиков, в данном случае 3.

Число в данном случае трехбайтовое. Старший байт записывается в Razr2, младший— в RazrO. При тактовой частоте 4 МГц мы можем получить за­держку до 4,19 с, если запишем в регистры все единицы: число 16 777 215 = SFFFFFF. Если же нам требуется, например, задержка в 1 секунду, то придет­ся записать число 800 ООО или $0С3500, если в полсекунды — число 400 ООО или$061А80.

Вооружившись этими знаниями, попробуем соорудить программу мигалки. Сначала давайте определимся с алгоритмом переключения из красного в зе­леный. Наиболее универсальным методом будет такой: каждый раз будем определять, в каком состоянии в данный момент находится светодиод (по состоянию какого-нибудь из задействованных выводов порта), и переклю­чать его в противоположное. Это может выглядеть таким образом:

/начало мигания

in temp,PortD /загружаем в temp состояние PortD

sbrc temp, 5 /если PD5 равен О, след. команду пропускаем

rjmp set_Green /переход на установку зеленого

sbi PortD,5 /PD5=1, устанавливаем красный

cbi PortD, 6 /PD6=0, устанавливаем красный

rjmp mig_end /переход на продолжение программы set_Green: /метка установка зеленого

cbi PortD,5 /PD5=0, устанавливаем зеленый

sbi PortD, б /PD6=1, устанавливаем зеленый mig_end: /метка конец мигания

Не углубляясь в подробности, заметим, что такой алгоритм (он, конечно, не единственно возможный) будет устойчив к начальным условиям: в каком бы состоянии к моменту его начала не нахбдились биты 5 и 6 (даже если свето­диод был совсем погашен), максимум через один цикл они придут в проти­воположное состояние и мигание начнется. Теперь осталось соединить все это в законченную программу: повторять процедуру мигания через промежу­ток времени, определяемый процедурой Delay. Программа будет выглядеть таким образом:

/Программа мигания светодиода /процессор Tiny2313, частота 4 МГц .include "tn2313def.inc" .def temp = rl6 /рабочий регистр .def RazrO = rl7 /разряды задержки

.def Razrl = rl8 .def Razr2 = rl9

ldi rie, low(RAMEND) /только для 2313 out SPL,rl6 /установка указателя стека

ldi temp,ObOliooooo /устанавливаем биты номер 5 и б в temp

out DDRD,temp /выводим это значение в регистр направления порта D

Mig_begin: /начало мигания

in temp,PortD /загружаем в temp состояние PortD

sbrc temp,5 /если PD5 равен О, след. команду пропускаем

rjnp set_Green /переход на установку зеленого

sbi PortD,5 /PD5=1, устанавливаем красный

cbi PortD,б /PD6=0, устанавливаем красный

гjmp mig_end /переход на продолжение программы set__Green: /метка установка зеленого

cbi PortD,5 /PD5=0, устанавливаем зеленый

sbi PortD,б /PD6=1, устанавливаем зеленый mig_end: /конец мигания

/пауза 0,5 с, N « $06lA80h

ldi Razr2,$06

ldi Razrl,$1A

ldi RazrO,$80 rcall Delay/ вызываем задержку гjmp Mig_begin /опять в начало

Delay: /процедура задержки

subi RazrO,1

sbci Razrl,О

sbci Razr2,0

brcc Delay ret

О назначении первых двух операторов программы мы поговорим позднее. Rcall — команда вызова процедуры (в данном случае Delay). После этой ко­манды всегда должна где-то встретиться команда ret (возврата из процеду­ры), иначе программа к основной последовательности операторов вернуться не «сумеет». Сама программа представляет собой бесконечный цикл, так как заканчивается оператором безусловного перехода обратно в начало (rjmp Migbegin). В данном случае мигание будет происходить с периодом в се­кунду (полсекунды красный, полсекунды зеленый), для его изменения нужно изменить записываемое в счетчики значение. Программа может служить хо­рошей основой для любимого развлечения радиолюбителей — конструиро­вания елочных гирлянд.

Заметки на полях

Кстати, о елочных шрляндах. На мой вкус, самый приличный вариант построе­ния тйкой гирлянды, который к тому же не встретишь в продаже — это обеспе­чить вместо раздражающего мигания медленное изменение из одного цвета в другой. Его несложно построить, используя явление биений: если сложить два почти совпадающих по частоте колебания через элемент, например, «Исклю­чающее ИЛИ», то на выходе возникнет колебание с меняющейся скважностью (см. рис. 15.8, г, аналогичный эффект можно получить и с другими логическими функциями). Если напряжение такой формы подать на лампочку, то высокочас­тотные составляющие не будут заметны, и лампочка будет медленно зажигаться и гаснуть. При очень близких, но все-таки не равных частотах, период биений может составить минуты, а если взять две разноцветных лампочки или свето­диода и включить их в противофазе, то гирлянда начнет медленно менять цвет с одного на другой. Причем в качестве одной из частот удобно взять частоту элек­трической сети, которая никогда точно не равна 50 Гц.

Для осуществления этого проекта на дискетной логике пришлось бы городить довольно громоздкую схему на счетчиках с предзагрузкой, причем долго под­гонять коэффициент деления так, чтобы смена цветов не была слишком быст­рой. А вот с помощью контроллера такая задача решается, что называется, в пять секунд. Для одной лампочки или светодиода почти не нужно даже менять схему по сравнению с рис. 19.2: достаточно подключить светоизлучающий элемент не непосредственно к выводу контроллера, а через ключевой транзи­стор. Коллекторную цепь его, в которую и будет включена лампочка или све­тодиод, при этом нужно питать от источника пульсирующего напряжения с час­тотой сети (от отдельной обмотки трансформатора через один диод, без сглаживания). А частоту на выводе МК, управляющую открыванием транзисто­ра, подогнать примерно под 50 Гц (то есть длительность задержки должна со­ставить примерно 0,01 с, для чего в счетчики придется записать число около 8000). Частоты будут складываться прямо на транзисторе: лампочка будет го­реть только тогда, когда и на коллекторе, и на его базе одновременно присут­ствует высокий уровень напряжения. Чтобы сделать эффект более заметным, можно поиграть со значением скважности. Поскольку у нас уже имеется два управляемых в противофазе вывода, можно добиться переливания из одного цвета в другой, а если усложнить программу, подключив еще несколько выво­дов МК, то можно получить весьма сложные и красивые эффекты. И, что при­ятно, экспериментируя с такой схемой, почти не придется браться за паяльник.

Оставить комментарий

микросхемы мощности Устройство импульсов питания пример приемника провода витков генератора выходе напряжение напряжения нагрузки радоэлектроника работы сигнал сигнала сигналов управления сопротивление усилитель усилителя усиления устройства схема теория транзистора транзисторов частоты