Сторожевой таймер
И снова здравствуйте.
Бывают ситуации, когда по тем или иным причинам, программа в микроконтроллере может зависнуть и устройство перестанет нормально функционировать. В этой ситуации поможет только сброс устройства вручную. Но это не всегда бывает возможно. Поэтому и был придуман сторожевой таймер, который может произвести сброс микроконтроллера.
Сторожевой таймер (контрольный таймер, англ. Watchdog timer — букв. «сторожевой пёс») — аппаратно реализованная схема контроля над зависанием системы. Представляет собой таймер, который периодически сбрасывается контролируемой системой. Если сброса не произошло в течение некоторого интервала времени, происходит принудительная перезагрузка системы. В некоторых случаях сторожевой таймер может посылать системе сигнал на перезагрузку («мягкая» перезагрузка), в других же — перезагрузка происходит аппаратно (замыканием сигнального провода RST или подобного ему).
Этот таймер тикает сам по себе, независимо от основной программы. Суть такова: в основной программе через определенные промежутки, вставляется код, который сбрасывает этот таймер. Когда таймер постоянно сбрасывается, то программа спокойно выполняется. Но, если его не сбросить, значит кусок кода основной программы не выполнился и завис, в этом случае таймер досчитает до определенного значения и сбросит полностью микроконтроллер. Программа начнет выполняться с самого сначала.
Характеристики сторожевого таймера:
- Отдельный генератор тактовых импульсов (128 кГц)
- Прерывания и возможность сброса системы
- Выбор режима генерации сброса от 16 миллисекунд до 8 секунд
- Режим защиты от сбоев при отключении только программированием fuse
Сторожевой таймер имеет всего один регистр** WDTCSR**.
Бит WDIF (7) - флаг поступления прерывания от сторожевого таймера (1 - если поступило прерывание (сбрасывается записью 1 во флаг)).
Бит WDIE (6) - разрешение прерывания от сторожевого таймера при записи в него 1.
Бит WDCE (4) - разрешение изменения режима работы сторожевого таймера (перед изменением режима работы или предделителя необходимо записать 1).
Бит WDE (3) - разрешение сброса системы сторожевым таймером при записи в него 1.
Бит WDP3 (5) и биты WDP2-WDP0 (2 - 0) управляют временем, через которое произойдет сброс или поступит прерывание от сторожевого таймера:
- 0000 - 2048 циклов (16 мс)
- 0001 - 4096 циклов (32 мс)
- 0010 - 8192 цикла (64 мс)
- 0011 - 16384 цикла (0.125 с)
- 0100 - 32768 циклов (0.25 с)
- 0101 - 65536 циклов (0.5 с)
- 0110 - 131072 цикла (1 с)
- 0111 - 262144 цикла (2 с)
- 1000 - 524288 циклов (4 с)
- 1001 - 1048576 циклов (8 с)
- 1010 - 1111 - резерв
Стоит также отметить, что при режиме работы (сброс и прерывание) сначала выполняется прерывание, а затем сброс. И если Fuse бит WDTON установлен в 0, в независимости от битов WDE и WDIE регистра WDTCR таймер будет сбрасывать систему по истечении времени на которое он настроен.
Также для сброса системы сторожевым таймером необходимо в бит WDRF (3) регистра MCUSR записать 1 (сбрасывается в 0 принудительно или по включению питания микроконтроллера).
Программирование сторожевого таймера
Команды для работы со сторожевым таймером:
#include <avr/wdt.h>
- подключение библиотеки для работы со сторожевым таймером
wdt_reset()
- сброс сторожевого таймера
wdt_enable()
- включение сторожевого таймера
wdt_disable()
- выключение сторожевого таймера
Для работы со сторожевым таймером для начала необходимо подключить библиотеку "wdt.h" в которой описаны все основные команды для работы со сторожевым таймером. Пример программы №1 будет включать сторожевой таймер, который в свою очередь будет сбрасывать микроконтроллер каждые 4 секунды. Пример программы №2 будет иметь более расширенный функционал: если микроконтроллер перестал отвечать, то он будет сброшен; если же он работает нормально, то при поступлении прерывания от сторожевого таймера каждые 8 секунд сторожевой таймер будет сбрасываться и начинать отсчет времени сначала. Это позволит контролировать работу устройства на протяжении всего времени.
Пример программы №1:
#include <avr/io.h> //подключаем стандартную библиотеку ввода/вывода
#include <avr/wdt.h> //подключаем библиотеку для работы со сторожевым таймером
int main(void)
{
wdt_enable(WDTO_4S); //включаем сторожевой таймер со сбросом через 4 секунды
while(1); //любая пользовательская программа
}
Пример программы №2:
#include <avr/io.h> //подключаем стандартную библиотеку ввода/вывода
#include <avr/wdt.h> //подключаем библиотеку для работы со сторожевым таймером
#include <avr/interrupt.h> //подключаем библиотеку для работы с прерываниями
ISR(WDT_vect) //подпрограмма обработки прерывания от сторожевого таймера
{
wdt_reset(); //сброс сторожевого таймера
WDTCSR = 1 << WDIE; //разрешение прерываний от сторожевого таймера (запрещаются автоматически при сбросе сторожевого таймера)
}
int main(void)
{
sei(); //разрешаем глобальные прерывания
wdt_enable(WDTO_8S); //включаем сторожевой таймер со сбросом через 4 секунды
WDTCSR = 1 << WDIE; //разрешение прерываний от сторожевого таймера
while(1); //любая пользовательская программа
}
Параметры функции wdt_enable()
обуславливают время сброса сторожевого таймера:
- WDTO_15MS
- WDTO_30MS
- WDTO_60MS
- WDTO_120MS
- WDTO_250MS
- WDTO_500MS
- WDTO_1S
- WDTO_2S
- WDTO_4S
- WDTO_8S
Если есть вопросы и предложения по этому уроку, пишите комментарии буду рад ответить на ваши вопросы.
Часть 1
Часть 2-1 Часть 2-2
Часть 3-1 Часть 3-2
Часть 4-1 Часть 4-2
Часть 5
Часть 6-1 Часть 6-2
Часть 7
Часть 8-1 Часть 8-2
Часть 9
Привет!
Этот пост был выбран Академией Голоса и попал в список программы поддержки качественных образовательных постов.
Ссылка на твой пост будет опубликована в отчете Академии.
Спасибо за полезный контент (ノ◕ヮ◕)ノ*:・゚✧