/**
* Copyright (c) 2022 - James Owens <jjo(at)arduando.com.br>
*
* Arquivo: 002_PiscarLED_watchdog.ino
* Arquivo: 29/11/2022 15:24:06
* Versão:
* Fonte: https://github.com/jjjowens/Arduando/tree/master/002_PiscarLED_watchdog
* Website: https://arduando.com.br
*
* Descrição: Esta é uma variação do sketch básico de fazer um LED piscar.
* No entanto nesta demonstração fazemos uso do recurso de watchdog
* incluido nos chips ATMega 328p e 32U4 entre outros. Para mais detalhes,
* veja o datasheet do 328p, seção 10.9.2 (WDTCSR – Watchdog Timer
* Control Register WDTCSR – Watchdog Timer Control Register:
* https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf#page=47
*
*
* DISCLAIMER:
* The author is in no way responsible for any problems or damage caused by
* using this code. Use at your own risk.
*
* LICENSE:
* This code is distributed under the GNU Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
* More details can be found at http://www.gnu.org/licenses/gpl.txt
*/
// Macro to executed assembly instruction 'wdr' (reset watchdog)
// Also defined in "avr/wdt.h"
#define wdt_reset() __asm__ __volatile__ ("wdr")
// Timer prescalers available for the watchdog.
#define WDT_16MS B01000000
#define WDT_32MS B01000001
#define WDT_64MS B01000010
#define WDT_125MS B01000011
#define WDT_250MS B01000100
#define WDT_500MS B01000101
#define WDT_1S B01000110
#define WDT_2S B01000111
#define WDT_4S B01100000
#define WDT_8S B01100001
// LED conectado no pino 10 através de um restor de 220 Ohms
#define LED_PIN 10
// Varável global acessada pela interrupção do watchdog
volatile bool _ledToggle = false;
// Declaração de funções auxiliares
void watchdogInit(uint8_t);
void setup()
{
pinMode(LED_PIN, OUTPUT);
watchdogInit(WDT_500MS);
}
void loop()
{
// Enquanto a flag = true mantém o led aceso
// Enquanto a flag = false mantém o led apagado
// A flag troca de estado toda vez que houver um timeout
// do temporizador do watchdog.
if (_ledToggle) digitalWrite(LED_PIN, HIGH);
else digitalWrite(LED_PIN, LOW);
}
//////////////////////////////////////////////
// Executado toda vez que houver uma interrupção gerada
// pelo contador do watchdog, o tempo pode ser controlado
// de acordo com divisores específicos da frequência base
// do oscilador interno de 128KHz. Após trocar o estado
// lógico da flag, reseta o contador do watchdog para
// que ele possa repetir o processo.
ISR(WDT_vect)
{
_ledToggle = !_ledToggle;
wdt_reset();
}
// Inicializa o controlador do watchdog de acordo com o valor
// do divisor/prescaler passado como argumento. Caso um valor
// não seja passado, assume 1s para o timeout. Para iniciar
// o Watchdog como interrupção, sem causar o processador a
// reiniciar, é necessário executar esta sequencia:
// 1: desabilitar interrupções
// 2: resetar o watchdog
// 3: habilitar o watchdog e o prescaler (registrador WDTCSR)
// 4. habilitar a interrupção e setar o prescaler (registrador WDTCSR)
// 5. habilitar interrupções
void watchdogInit(byte timeout_mask = WDT_1S)
{
cli();
wdt_reset();
WDTCSR |= B00011000;
WDTCSR = timeout_mask;
sei();
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
led1:A
led1:C
r1:1
r1:2