Юрий Ревич - Занимательная микроэлектроника
- Название:Занимательная микроэлектроника
- Автор:
- Жанр:
- Издательство:БХВ-Петербург
- Год:2007
- Город:Санкт-Петербург
- ISBN:978-5-9775-0080-7
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Юрий Ревич - Занимательная микроэлектроника краткое содержание
Для широкого круга радиолюбителей
Занимательная микроэлектроника - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Вторая особенность таймеров семейства Меда — наличие асинхронного режима работы для одного из таймеров (в большинстве моделей это Timer 2). Тогда его можно завести от независимого источника импульсов (от внешней частоты или низкочастотного кварца, в том числе часового 32 768 Гц), и он может считать независимо от работы всей остальной схемы. Теоретически эту функцию можно использовать как RTC, но на практике это неудобно (нет ни счета времени, ни календаря), зато ее очень удобно применять для вывода МК из «сна» по времени. В режиме энергосбережения под названием Power Save МК будет «просыпаться» каждое прерывание от Timer 2, и подсчетом этих прерываний его можно окончательно «разбудить» автоматически через нужный промежуток времени.
Сторожевой (watchdog) таймер — одно из самых полезных устройств в составе микроконтроллеров AVR. Причем это неочевидно: в нормальном режиме работы, когда все настроено идеально, он вовсе не нужен. Но представьте себе такую ситуацию: МК настроен на прием данных от компьютера, причем по простейшей схеме из главы 16 , с непрерывным опросом бита UDRE. К примеру, он ожидает шесть байтов, как в нашей программе, но на пятом байте ПК внезапно ломается (кто-то прошел и ногой выдернул провод из COM-порта). Что будет с контроллером? Естественно, он повиснет в ожидании байта, и из этого состояния его не удастся вывести никаким способом, кроме полного сброса. Еще более опасны в этом отношении наши процедуры опроса линии по интерфейсу I 2С — при программировании для ПК нам бы «голову оторвали» за такую организацию процесса.
И тем не менее здесь это нормальный способ программирования — нецелесообразно усложнять программу на порядки только для того, чтобы исключить все возможные ситуации, которые, может быть, за время «жизни» прибора вообще ни разу не произойдут. В ПК все иначе: во-первых, там есть удобные инструменты для таких случаев, во-вторых, там от одной программы могут зависеть и другие. Вот если бы мы на МК сооружали устройство управления космическим кораблем — тогда другое дело…
Но все же, как быть в таких случаях — ставить специальную кнопку Reset (как в компьютере) или писать в инструкции «если прибор не реагирует, то выключите и включите питание»? Вот тут-то на помощь и приходит сторожевой таймер, который, будучи включен, выполняет одну-единственную операцию: считает импульсы от собственного генератора (абсолютно независимо от всей остальной схемы МК), и когда досчитает до заданного их числа, не обращая внимания ни на что, попросту сбрасывает процессор, как будто был подан сигнал Reset. Самая длительная выдержка, которую можно получить от сторожевого таймера, составляет примерно 2 с (с большим разбросом, т. к. задающий генератор простейшего RC-типа).
Ну и что с этим делать, спросите вы? Нельзя же сбрасывать МК каждые две секунды «на всякий случай» и начинать работу заново, правда? Но этого и не требуется: достаточно завести сторожевой таймер, а потом сбрасывать его в исходное состояние, не дожидаясь, пока он сбросит контроллер. Это можно делать специально по таймеру или в любой другой периодически протекающей процедуре, которая должна выполняться раньше, чем таймер успеет сбросить процессор. Тогда, если МК завис по любой причине (даже просто из-за ошибки в программе), таймер сработает и приведет все в начальное состояние. В том числе, кстати, «разбудит» МК, даже если тот находится в самом глубоком «сне» (в режиме Power Down).
Для примера разберем такой случай возможного использования сторожевого таймера. В измерителе с часами, который был описан в главе 16 , опасная ситуация может возникнуть, если по каким-то причинам не «придет» прерывание от часов. Это может произойти, например, если сами часы «повисли» (у них ведь тоже достаточно сложный алгоритм) или просто «потерялся» фронт очередного импульса. А так как мы настраиваемся на круглогодичную работу этого прибора, то подобную ситуацию следует рассматривать как вероятную. В конце концов, космическая частица может прилететь и все нарушить — согласно некоторым исследованиям, сбои такого рода неизбежны с вероятностью примерно 1 сбой на 1000 часов работы (правда, автор этих строк лично ничего такого не наблюдал, но и специально вопрос не исследовал). В этом случае неплохо выполнить процедуру включения прибора заново: в начале программы мы в том числе инициализируем и часы, а уж если они совсем сломались, тут ничего не поделаешь.
Для этого перед началом основного цикла инициализируем сторожевой таймер:
;запускаем WDT на 2 сек:
wdr ;команда на сброс — так рекомендуется
ldi temp,(1<<
out WDTCR,temp
ldi temp,(1<<<<<
out WDTCR,temp
Теперь осталось по каждому прерыванию от часов (INTO) просто сбрасывать сторожевой таймер:
EXT_INT0:
wdr ;сброс сторожевого таймера
…
Так как прерывание должно возникать каждую секунду, то мы сбрасываем таймер заведомо раньше, чем он сработает, и он начнет отсчет выдержки сначала. Если же что-то (часы или программа) «повиснет», то произойдет общий сброс МК, и он начнет работать опять. Причем после чтения данных из flash мы сможем это обнаружить: если помните, мы в кадр времени записывали байт сбоев, в котором установленный бит 3 означал, что сброс произошел именно от сторожевого таймера.
В этом деле есть единственный «тонкий» момент: если у нас где-то в программе имеется процедура с запрещением прерываний, выполняющаяся дольше, чем 2 с, то сторожевой таймер на время ее выполнения, естественно, следует выключить (не просто сбросить, а вообще запретить его работу). У нас такая процедура есть — это чтение данных из памяти, при котором даже индикация выключается. Вызов этой процедуры придется переписать так, как показано в листинге 17.5.
Листинг 17.5
proc_F2: ;F2 читать flash
cli ;запрещаем прерывания выключить WD:
wdr ;Reset WDT
in temp, WDTCR
ori temp,(1<<
out WDTCR, temp
ldi temp,(0< ;выключить WDT
out WDTCR, temp
rcall ReadFullFlash ;читаем данные
;запускаем WDT обратно, 2 с
wdr ;команда на сброс
ldi temp,(1<
ldi temp,(1«WDP0)|(1«WDP1)|(1<<
out WDTCR,temp
sei ;разрешаем прерывания — необязательно, уже есть в ReadFullFlash
rjmp Gcykle
Заметьте, что после такой длительной процедуры можно прерывания и не разрешать (для этого придется убрать разрешение и из самой процедуры ReadFullFlash) — а вдруг мы чего-то нарушили в работе? Тогда контроллер просто перезапустится с нуля, и работа восстановится.
Глава 18
Персональный компьютер и системы на МК
Интервал:
Закладка: