Добавить в корзинуПозвонить
Найти в Дзене
Старый Регенератор

WatchDog таймер Arduino

Во многих программах требуется выработка временных интервалов. Здесь показан пример использования прерывания таймера Watchdog
Контроллер Arduino UNO
Контроллер Arduino UNO

Во многих программах требуется выработка временных интервалов. Это бывает необходимо для задержек, периодических опросов внешних устройств, обновления информации на индикаторах и дисплеях и т. п. Использование циклов ожиданий крайне непродуктивно, т. к. в это время процессор ничем полезным не занят.

Здесь будет показан пример использования прерывания таймера Watchdog конструктора Arduino UNO для генерации временных интервалов.

Перед тем, как приступить к работе, желательно иметь в наличии принципиальную схему контроллера Arduino UNO и описание на собственно контроллер ATmega328, т. к. описание работы будет базироваться на этих документах. Естественно предполагается, что на компьютере установлена среда программирования ArduinoIDE.

Попробуем запустить какую-нибудь индикацию того, что контроллер "живет". Для этого заставим мигать расположенный на плате светодиод примерно раз в секунду. Обычно для отсчета временных интервалов используется таймер. В нашем случае не будем занимать один из трех штатных таймеров, а воспользуемся таймером Watchdog. Он, конечно, не имеет хорошей точности, т. к. работает от RC-генератора, но для многих применений этого вполне достаточно.

Настраивается таймер через установку битов в регистре WDTCSR (Watchdog Timer Control Register). Адрес регистра — 0x60. Расположение бит регистра приведено в табл. 1.

Таблица 1. Регистр WDTCSR
Таблица 1. Регистр WDTCSR

Возможные режимы работы таймера приведены в табл. 2.

Таблица 1. Режимы работы таймера WATCHDOG
Таблица 1. Режимы работы таймера WATCHDOG

Бит WDTON управляет переводом таймера в режим системного сброса. Этот бит находится в специальных конфигурационных байтах и по умолчанию установлен в "1", поэтому его программирование рассматривать не будем.

Бит WDCE (Watchdog Change Enable) регистра WDTCSR управляет возможностью изменения состояния остальных битов этого регистра и должен быть установлен в "1", если необходимо изменить остальные биты регистра. Если этого не сделать, то изменения не будут записаны в регистр.

В процессе отладки программы (а также проработки примеров программ из инструкции к контроллеру Atmega328) было обнаружено следующее. Если установить в "1" только бит WDCE, например, командой:

WDTCSR = (1 << WDCE);

то установить делитель не удастся. Следует одновременно установить в "1" и бит WDE, т. е. выполнить команду:

WDTCSR = (1 << WDCE) | (1 << WDE);

а затем уже устанавливать биты делителя. Сбрасывать биты WDCE и WDE не требуется — они сбрасываются аппаратно, как написано в инструкции на контроллер — через 4 такта. Именно такая последовательность установки предделителя таймера приведена в примере инструкции на контроллер.

Установка бит WDP0-WDP3 регистра WDTCSR для изменения делителя таймера приведена в табл. 3.

Таблица 3. Установка предделителя таймера.
Таблица 3. Установка предделителя таймера.

После этих предварительных замечаний можно привести вариант программы, дополненной работой с Watchdog таймером. Подпрограмма SetWatchdogTimer() производит настройку таймера, а ISR(WDT_vect) — обрабатывает его прерывания.

void setup() {
pinMode(LED_BUILTIN, OUTPUT); // настройка светодиода индикации
cli(); // запрещаем прерывания перед настройкой
SetWatchdogTimer();
sei(); // разрешаем прерывания после настройки
}
void loop() { }
// Подпрограмма настройки прерываний сторожевого таймера
void SetWatchdogTimer(){
WDTCSR = (1 << WDCE) | (1 << WDE);
// установка делителя 0,5 сек.
WDTCSR = (0 << WDP3) | (1 << WDP2) | (0 << WDP1) | (1 << WDP0);
// разрешение прерываний таймера
WDTCSR |= (1 << WDIE);
}
// Программа обработки прерывания сторожевого таймера
ISR(WDT_vect){
// мигаем светодиодом раз в секунду
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); }

И, загрузив программу в контроллер, увидеть, что контроллер "живет", подмигивая желтым глазком.