Сторожевой таймер (Watchdog Timer - «сторожевой пёс») в PIC микроконтроллерах не требует внешних компонентов и представляет из себя обычный счётчик, непрерывно тактируемый от автономного RC-генератора. Сторожевой таймер можно глобально включать/отключать в битах конфигурации #pragma config WDTE = OFF|ON
- если включён WDTE = ON
, то в случае переполнения счётчика обычно происходит аппаратный сброс микроконтроллера, хотя также возможен особый случай использования сторожевого таймера - чтобы вывести микроконтроллер из спящего режима.
Зачем нужен сторожевой таймер ? Программы в микроконтроллерах напрямую взаимодействуют с железом и иногда случаются внештатные ситуации, когда по тем или иным причинам программа может зависнуть - причиной тому может быть как аппаратный сбой, так и ошибка программиста. В таких случаях нужно идти и ручками выдергивать питание или нажимать кнопочку сброса. Альтернативой этому как раз и является использование сторожевого таймера, который сбросит микроконтроллер автоматически если что-то пошло не так.
/*
xc8 --chip=16f648A main.c
*/
#include <xc.h>
#include <stdint.h>
#pragma config WDTE = ON
int main() {
// The WDT has a nominal time-out period of 18 ms (with no prescaler).
// If longer time-out periods are desired, a postscaler with a division ratio
// of up to 1:128 can be assigned to the WDT under
// software control by writing to the OPTION register. Thus,
// time-out periods up to 2.3 seconds can be realized
OPTION_REGbits.PS0 = OPTION_REGbits.PS1 = OPTION_REGbits.PS2 = 1; // 1:128; 2.3 sec
OPTION_REGbits.PSA = 1; // prescaler is assigned to watchdog
// looks like STATUS [TO, PD] are not implemented in original PICSim - always 0
PORTB = STATUS;
PORTA = TRISB = TRISA = 0;
RA0 = 0;
for (uint16_t i = 333; --i;); // simple delay
RA0 = 1;
while(1) {
// CLRWDT();
// do something useful
}
return 0;
}
Минимальный период срабатывания сторожевого таймера у PIC16F648A микроконтроллера 18 миллисекунд, максимальный 0.018*128=2.304
секунды. Так как в данном примере программист забыл программно очищать счётчик сторожевого таймера специальной командой CLRWDT();
то через каждые 2.3 секунды микроконтроллер сбрасывается и в результате светодиод RA0 мигает. Если раскомментировать // CLRWDT();
светодиод RA0 конечно же будет светиться непрерывно. Причину сброса микроконтроллера по идее можно узнать по состоянию флагов TO, PD в регистре STATUS, хотя похоже в picsim это не реализовано.
Что касается спящий режима, то он позволяет значительно снизить энергопотребление. Для перехода а спящий режим у PIC микроконтроллеров предусмотрена специальная команда SPEEP()
, после которой тактирование микроконтроллера прекращаются, текущее состояние всех регистров в том числе и портов ввода-вывода сохраняется и потребление энергии сводится к минимуму - обычно единицы микроампер. Выйти из спящего режима можно либо по прерыванию либо при срабатывании сторожевого таймера.
/*
xc8 --chip=16f648A main.c
*/
#include <xc.h>
#include <stdint.h>
#pragma config WDTE = ON
int main() {
OPTION_REGbits.PS1 = OPTION_REGbits.PS2 = 1;
OPTION_REGbits.PS0 = 0; // 1:64; 1.152 sec
OPTION_REGbits.PSA = 1; // prescaler is assigned to watchdog
PORTB = TRISB = 0;
uint8_t last_led = 0;
while(1) {
SLEEP();
last_led <<= 1;
if (!last_led) {
last_led = 1;
}
PORTB = last_led;
}
return 0;
}
В данном примере в отличие от предыдущего микроконтроллер не сбрасывается а просыпается от сторожевого таймера каждые 1.152 секунды, передвигает светодиод и засыпает заново. Основное энергопотребление приходится только на свечение светодиода.
Сторожевой таймер является очень простым и полезным инструментом, придающим надёжности разрабатываемой системе. Особенно когда устройство покидает пределы уютной лаборатории и переходит из бережных рук разработчиков к реальным пользователям.
Далее попробуем линейку PIC18 микроконтроллеров и начнём с символьного LCD дисплея на базе контроллера HD44780.