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





Необходимо также учитывать то, что было сказано ранее про отслеживание окончания посылки, чтобы не "обрубить" передачу последнего байта. Еще более эффективным методом работы с UART будет аппаратное обнаружение подключенной линии RS-232, когда переход в режим Sleep просто запрещается. Это можно сделать учитывая, например, что при подключении кабеля RS-232 на линии RxD (до преобразователя уровня) должен "висеть" отрицательный потенциал. Можно и договориться о том, что "верхняя" программа устанавливает линию RTS либо DTR в нужное состояние, или подобрать преобразователь RS-232/UART, имеющий встроенный механизм обнаружения линии (типа МАХ3319). Более подробно мы здесь рассматривать этот вопрос не будем. Теперь необходимо разобраться с прерываниями и установкой флага fsleep. Прерывание таймера иллюстрирует листинг 14.4.

Листинг 14,4
Т1М1_СОМРА: inc count_min
cpi count_min,1 /через 7,5 с разрешаем INT1 brne schet_time
ldi temp, (1«INT1) | (1«INT0) /разрешение INTl и INTO out GICR,temp /GIMSK и GIGR - синонимы /очищаем регистр флагов прерываний ldi temp,$FF
out GIFR,temp /GIFR очищается записью единиц schet_time: /здесь отсчет времени
sbrs count_min,3 /если бит 3=1, то прошло 8 интервалов =1 мин reti /иначе выходим
clr count_min /в след. раз — сначала
sbr Flag,$80 /устанавливаем бит x_sleep
clr temp /останавливаем таймер
out TCCRIB,temp
/очищаем регистр прерываний ldi temp,$FF
out TIFR,temp /очищается записью единиц reti /выходим

При отсутствии кнопки на этом можно было бы закончить— через 1 минуту после включения у нас измеритель уходит в "сон", из которого его можно вывести только выключением-включением питания или подачей сигнала Reset. Но мы хотим все сделать грамотно, потому используем кнопку. Прерывание ПМТ1 тогда будет выглядеть так, как в листинге 14.5.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ EXT_INT1:
ldi temp, (1«INT0) ;запрещаем INTl и разрешаем INTO out GICR,temp'
sbrc Flag, 7 /если были во сне, то больше ничего не делаем -/следующей после выхода будет первая команда после sleep reti /выход из прерывания
clr temp /иначе готовимся ко сну
out TCCRlB,temp /останавливаем таймер
clr -temp /чистим счетные регистры таймера
out TCNT1H,temp
out TCNT1L,temp
ldi temp,ObOOOOllOl /заново запускаем out TCCRlB,temp /очищаем регистр прерываний
ldi temp,$FF
out TIFR,temp /очищается записью единиц, ldi count_min,7 /на интервал 7,5 с reti

Теперь измеритель будет работать так, как мы и задумывали: после включения через 1 минуту он уходит в режим энергосбережения, когда индикация гаснет и потребление минимизируется. Если нажать на кнопку, то МК "проснется" и выполнит все процедуры после команды sleep. Если ничего не делать, то через минуту измеритель опять "заснет". Если нажать до истечения этого срока на кнопку (но не ранее, чем через 7,5 с), то он "заснет" через 7,5 с после нажатия. В принципе таймер можно было бы и не останавливать перед очисткой, но так мы более уверены, что он начнет отсчет с самого начала. Время задержки вы легко можете регулировать, просто меняя число, которое загружается в регистры OCRIAH/L. ОНО рассчитывается исходя из формулы: время задержки в секундах равно частоте кварца в герцах, деленной на коэффициент предварительного деления (1024) и на это число. Например, если вместо 29 297 загрузить 11 719, то пауза до засыпания по нажатию кнопки станет равной 3 с, а время работы сократится менее чем до полуминуты. Чтобы увеличить время "бодрствования" вдвое, команду sbrs countmin, з в прерывании таймера нужно заменить на sbrs countmin, 4.

Использование сторожевого таймера
Сторожевой таймер (Watchdog Timer, WDT) — одно из самых полезных устройств в составе микроконтроллеров. Причем его полезность неочевидна: в нормальном режиме работы, когда все настроено идеально, он вовсе не нужен. Но представьте себе такую ситуацию: МК настроен на прием данных с компьютера с непрерывным опросом бита UDRE. К примеру, он ожидает шесть байтов, как в нашей программе из главы 13, но на пятом байте ПК внезапно ломается (кто-то прошел и ногой выдернул провод из СОМ-порта). Что будет с контроллером? Естественно, он повиснет в ожидании байта, и из этого состояния его не удастся вывести никаким способом, кроме полного сброса. Другой пример: часы реального времени, описанные в главе 12, от которых зависит работоспособность всей системы, по сути также представляют собой контроллер, и подобные устройства могут "зависать" ничуть не хуже любых других, вследствие ошибок в функционировании или из-за помех. В таком случае вся система требует переинициализации путем сброса и запуска с нуля.

Вот для предотвращения таких ситуаций и нужен WDT, который сбросит МК по истечении некоторого срока, если его вовремя не остановить. Он подключается к автономному Ж7-генератору с частотой примерно 1 МГц при питании 5 В (в старых моделях эта частота могла уменьшаться пропорционально снижению питания МК, в Mega ее стабильность несколько повышена). Заметим кстати, что начальная задержка при включении МК (та, что определяется ячейками SUTI. .0, см. главу 2), точнее, ее постоянная составляющая, определяется именно генератором сторожевого таймера.

Другая функция WDT была упомянута в главе 4: МК, находящийся в любом из режимов энергосбережения, можно принудительно "разбудить," сторожевым таймером, если "пробу-' ждающее" событие не наступило. В отличие от выхода из "сна" через внешнее событие, при этом выполнится не прерывание, а начальная процедура RESET, как при включении. Отметим, что включенный WDT потребляет ток примерно 70 мкА. Для того чтобы вследствие какой-нибудь помехи WDT не запустился и, главное, не выключился случайно, и для запуска и для выключения его предусмотрена довольно "навороченная" процедура, которая к тому же довольно "мутно" описана в документации. Причем процедура эта различается для МК семейств Tiny, Classic и Mega, что дало зачем-то авторам техдокументации основание для ввода специальных "уровней управления" режимом WDT. На самом деле все гораздо проще: во-первых, в некоторых моделях Tiny и во всех Mega есть fuse-бит WDTON, который устанавливает, включен ли изначально WDT или выключен. По умолчанию WDTON находится в незапрограммиро-ванном состоянии (лог. 1), означающее, что WDT выключен, и для приведения в действие его следует специально инициализировать.

Наличие WDTON — довольно удобное свойство для того, чтобы не возиться с включением WDT самостоятельно, но оно в значительной мере обесценивается тем фактом, что по умолчанию сторожевой таймер запрограммирован на минимальный интервал (~15 мс), который все равно, как правило, приходится увеличивать. А эта процедура ничуть не проще, чем просто включить таймер, одновременно установив его на нужный интервал, потому далее мы будем считать, что WDTON МЫ не трогали. Тогда вариантов процедур включения/выключения окажется всего два: попроще для семейств Tiny и Classic (и для Mega в режиме совместимости с Classic при соответствующем установленном fuse-бите, для ATmega8535 это S8535C) и посложнее для Mega. Управляют режимом включения/выключения два разряда регистра WDTCR: бит разрешения изменений WDCE (В некоторых моделях он называется WDTOE) И бит включения WDE. ДЛЯ семейства Classic и Tiny для включения достаточно установить бит WDE В единичное состояние, одновременно, если надо, устанавливается и период таймера битами WDP2. .0 того же регистра, задающими коэффициент деления генератора (состояние ООО соответствует минимальному периоду -15 мс, 110 — примерно 1 с, 111 задает максимальный период немного менее 2 с). Перед такими операциями всегда рекомендуется сбрасывать WDT командой wdr (иначе таймер может начать отсчет не с начала, и произойдет непроизвольный сброс МК), как показано в листинге 14.6.



     
 

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