Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





Доработка программы
Доработку программы измерителя из главы 10, дополненного flash-памятью и часами, как описано в главе 12, начнем с того, что включим по умолчанию питание аналоговой части. Для этого в разделе начальной загрузки, там, где устанавливаются порты ("установка портов вход-выход"), вместо команды ldi temp, оыооооооо (перед) запишем ldi temp, 0Ы1010000 /выводы PD6-7 задействованы для светодиода out DDRD,temp - После этого вывод 18 сконфигурирован на выход, причем уровень должен быть нулевым (для надежности можно добавить еще оператор cbi PortD, 4).
Теперь опять инициализируем Timerl. При тактовой частоте 4 МГц он может дать выдержку максимум 15 с, настроим его на вдвое меньший интервал — 7,5 с. В загрузочную секцию вместо строк инициализации TimerO (ldi temp, (1«TO1EO) и out TIMSK, temp) добавляем код листинга, 14.1.

111Я11Я
;======== Set Timer 1
ldi temp,high(2 92 97) out OCRlAH,temp ldi temp,low(29297) out OCRlAL,temp ldi temp,ObOOOOllOl
out TCCRlB,temp ;1/1024; очистить после совпадения ldi temp, (1< ;по совпадению для Timer 1'и переполнению Timer 0 out TIMSK,temp
;очищаем регистр флагов прерываний ldi temp,$FF
out TIFR,temp ;очищается записью единиц

Кроме этого, введем переменную countmin, с помощью которой будем считать 7,5-секундные интервалы. В секции объявления переменных добавим:
.def count_min = г23; счетчик 7,5-секундных интервалов
А в секции начальных установок его не забудем обнулить:
clr countjnin
Далее введем специальный флаг fsieep (пусть будет бит 7 в регистре Flag), который будет сигнализировать о режиме. Если этот бит установлен — пора спать, если обнулен — работаем, как ни в чем не бывало. По умолчанию он обнулен, т. к. обнуляется регистр Flag, и нам ничего не грозит, если мы вставим в основной цикл запуск режима энергосбережения (листинг 14.2).
Gcykle:
sbrs Flag,7 ;если бит 7 установлен, то засыпаем rjmp Gcykle ;иначе бесконечный цикл cli ;на всякий случай запрещаем прерывания ;все порты на вход, и нули в разряды, кроме PortD, 4
clr temp
out DDRB,temp
out DDRC,temp
out PortB,temp
out PortC,temp

ldi temp,ОЬОООЮООО /выключение аналогового питания out DDRD,temp ;разряд 4 на выход out PortD,temp ;и в единичное состояние ldi temp, 0Ы1100010 /разрешение Sleep, режим Standby /прерывание INT1 по уровню, прерывание INTO по спаду out MCUCR,temp ldi temp, (1«INT1) | (1«INT0) /разрешение- INT 1 и INTO out GICR,temp

/очищаем регистр флагов прерываний ldi temp,$FF
out GIFR,temp /GIFR очищается записью единиц sei /разрешаем прерывания Sleep /наконец, спим
cbr Flag, $80 :по выходу из сна сбрасываем флаг f_sleep clr countjnin /отсчет времени-сначала /установка портов вход-выход обратно cli /на всякий случай запрещаем прерывания
<установка DDRB, DDRC... >
ldi temp, 0Ы1010000 /знак минус и питание
out DDRD,temp
clr temp
out PortD,temp /включить аналоговое питание out MCUCR,temp /запрещаем режим Sleep out TCNTlH,temp /чистим счетные регистры таймера out TCNT1L,temp
ldi temp,ObOOOOllOl /запускаем таймер
out TCCRlB,temp /1/1024 очистить после совпадения < обновляем часы, см. главу 12> sei /разрешаем прерывания rjmp Gcykle /бесконечный цикл

Прерывание по уровню (а не по спаду или фронту) для INT1 мы вынуждены здесь установить, т. к. только этот режим осуществляется асинхронно, и может разбудить МК (за исключением малополезного режима Idle). В любом случае мы вынуждены после включения запрещать прерывания на достаточно долгий срок, чтобы защититься от дребезга кнопки, поэтому прерывание по уровню не вызовет проблем. Если же этот режим применять неудобно (так может быть в ряде программ реального времени, где неизвестен заранее ни промежуток до прихода следующего "пробуждающего" сигнала, ни длительность низкого уровня), то следует задействовать прерывание INT2, которое выполняется как раз по фронту или спаду, и притом обнаруживается асинхронно. Отметим, что здесь также не учитывается использование UART, если это необходимо — когда в основном цикле контроллер все время "висит" в ожидании прихода байта по этому порту, как описано в главе 13, то вход в режим "сна" может никогда не выполниться. В этой ситуации нужно либо прибегнуть к прерываниям UART, либо поменять процедуру ожидания прихода символа incom (исключив из нее безусловный переход, так, чтобы непрерывно выполнялся весь основной цикл) так, как показано в листинге 14.3.

Листинг 14.3
sbis UCSRA,RXC
ret
in temp, UDR
ret
Gcykle:
rcall in_comS /однократно опрашиваем UART
<что-то делаем, если пришел байт
sbrs Flag,7 ... и т. д. — обработка режима sleep



     
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru