Watchdog Timer in 8051, Tested and working code
What is watch Dog timer:
A watchdog timer (WDT) is a hardware timer that automatically generates a system reset if the main program neglects to periodically service it. It is often used to automatically reset an embedded device that hangs because of a software or hardware fault.
How WDT works?
1) Initialise the WDT
2) Now the WDT will start running until it reaches the set time out .
3) Clear the WDT periodically in different stages of the code to clear the WDT which makes the WDT to initilise again to zero and start running again, when it encounters another clear statement, it is again set to zero, this means that, as long as the code is running, WDT counter will be set back to zero, avoiding to reach its time out.
4) When the code hangs due to some unhanded exception in the HW/SW then the WDT reaches its maximum time out. This sends a reset sequence to the micro controller to restart the code to start over again.
3) Clear the WDT periodically in different stages of the code to clear the WDT which makes the WDT to initilise again to zero and start running again, when it encounters another clear statement, it is again set to zero, this means that, as long as the code is running, WDT counter will be set back to zero, avoiding to reach its time out.
4) When the code hangs due to some unhanded exception in the HW/SW then the WDT reaches its maximum time out. This sends a reset sequence to the micro controller to restart the code to start over again.
About Watch Dog Timer in 8051
According to the data sheet, There is a Watch dog timer inside 8051
One thing should be noted that the WDT in 8051 has two variants
1)With Prescalar, where we can configure the timeout selection with WDTPRG register
2)With out Prescalar, a fixed 8 ms time out WDT. or for 16383 machine cycles
In AT89C51RD2/87C51RD2 we can use the Prescalar,
but there is no Prescalar in AT89S52/S51/C51/C52
How to use WDT in 8051 ?
For AT89C51RD2/87C51RD2
/*
Selected Time-out
WDTPRG|=0x00 (2^14 - 1) machine cycles, 16. 3 ms @ FOSCA =12 MHz
WDTPRG|=0x01 (2^15 - 1) machine cycles, 32.7 ms @ FOSCA=12 MHz
WDTPRG|=0x02 (2^16 - 1) machine cycles, 65. 5 ms @ FOSCA=12 MHz
WDTPRG|=0x03 (2^17 - 1) machine cycles, 131 ms @ FOSCA=12 MHz
WDTPRG|=0x04 (2^18 - 1) machine cycles, 262 ms @ FOSCA=12 MHz
WDTPRG|=0x05 (2^19 - 1) machine cycles, 542 ms @ FOSCA=12 MHz
WDTPRG|=0x06 (2^20 - 1) machine cycles, 1.05 s @ FOSCA=12 MHz
WDTPRG|=0x07 (2^21 - 1) machine cycles, 2.09 s @ FOSCA=12 MHz
*/
WDTPRG|=0x07;/*2.275s @ FOSCA=11.059200 MHz
---------------------------------------------------------------------------------------
Step1: Initialise the WDT
WDTPRG|=0x07; //(2^21 - 1) machine cycles, 2.09 s @ FOSCA=12 MHz
/* watchdog start sequence */
WDTRST=0x1E;
WDTRST=0xE1;
Step 2: Clear the WDT
WDTRST=0x1E;// Clear WDT sequence step1
WDTRST=0xE1; // Clear WDT sequence step2
--------------------------------------------------------------------------------------------------
For AT89S52/S51/C51/C52
Step1: Initialise the WDT
WDTRST=0x1E; // Initilising the WDT step1
WDTRST=0XE1; // Initilising the WDT step2
Step 2: Clear the WDT
WDTRST=0x1E;// Clear WDT sequence step1
WDTRST=0xE1; // Clear WDT sequence step2
(According to the data sheet step 1 and step 2 both are same)
---------------------------------------------------------------
Selected Time-out
WDTPRG|=0x00 (2^14 - 1) machine cycles, 16. 3 ms @ FOSCA =12 MHz
WDTPRG|=0x01 (2^15 - 1) machine cycles, 32.7 ms @ FOSCA=12 MHz
WDTPRG|=0x02 (2^16 - 1) machine cycles, 65. 5 ms @ FOSCA=12 MHz
WDTPRG|=0x03 (2^17 - 1) machine cycles, 131 ms @ FOSCA=12 MHz
WDTPRG|=0x04 (2^18 - 1) machine cycles, 262 ms @ FOSCA=12 MHz
WDTPRG|=0x05 (2^19 - 1) machine cycles, 542 ms @ FOSCA=12 MHz
WDTPRG|=0x06 (2^20 - 1) machine cycles, 1.05 s @ FOSCA=12 MHz
WDTPRG|=0x07 (2^21 - 1) machine cycles, 2.09 s @ FOSCA=12 MHz
*/
WDTPRG|=0x07;/*2.275s @ FOSCA=11.059200 MHz
---------------------------------------------------------------------------------------
Step1: Initialise the WDT
WDTPRG|=0x07; //(2^21 - 1) machine cycles, 2.09 s @ FOSCA=12 MHz
/* watchdog start sequence */
WDTRST=0x1E;
WDTRST=0xE1;
Step 2: Clear the WDT
--------------------------------------------------------------------------------------------------
WDTRST=0x1E;// Clear WDT sequence step1
WDTRST=0xE1; // Clear WDT sequence step2
For AT89S52/S51/C51/C52
Step1: Initialise the WDT
WDTRST=0x1E; // Initilising the WDT step1
WDTRST=0XE1; // Initilising the WDT step2
WDTRST=0x1E;// Clear WDT sequence step1
WDTRST=0xE1; // Clear WDT sequence step2
(According to the data sheet step 1 and step 2 both are same)
---------------------------------------------------------------
(According to the data sheet step 1 and step 2 both are same)
---------------------------------------------------------------
Write a timer based delay routine which generates 2ms time delay.
/*if time variable value is 1, then it generates 2ms of delay;/*
void delay(unsigned int time)
{
int count=0;
while(count!=time)
{
TMOD=0x01; //16-bit timer0 selected
TH0=0xF8; // Loading high byte in TH
TL0=0xCC; // Loaded low byte in TL
TR0=1; // Running the timer
while(!TF0); //Checking the timer flag register if it is not equal to 1
TR0 = 0; // If TF0=1 stop the timer
TF0 = 0; // Clear the Timer Flag bit for next calculation
count++;
}
}
----------------------------------------------------
Clear the WDT in the delay loop as shown below, so when ever a delay is executed in the main, WDT is cleared, which make sure that WDT will not execute, if the code hangs, then the delay will not be executed, the WDT is not cleared, the WDT will count upto its maximum timeout, and sends a reset sequence to the reset register of the micro controller.
*********This code is shown for AT89S52/S51/C51/C52 *********
#include<reg51.h>
void delay(unsigned int time)
{
int count=0;
while(count!=time)
{
WDTRST=0x1E;// Clear WDT sequence step1
WDTRST=0xE1; // Clear WDT sequence step2
TMOD=0x01; //16-bit timer0 selected
TH0=0xF8; // Loading high byte in TH
TL0=0xCC; // Loaded low byte in TL
TR0=1; // Running the timer
while(!TF0); //Checking the timer flag register if it is not equal to 1
TR0 = 0; // If TF0=1 stop the timer
TF0 = 0; // Clear the Timer Flag bit for next calculation
count++;
WDTRST=0x1E; // Clear WDT sequence step1
WDTRST=0xE1; // Clear WDT sequence step2
}
}
void main()
{
// initialisations if any
WDTRST=0x1E; // Initilising the WDT step1
WDTRST=0XE1; // Initilising the WDT step2
while(1)
{
//statements
delay(1);
//statements
while(1);
}
--------------------------------------------------------
Clear the WDT in the delay loop as shown below, so when ever a delay is executed in the main, WDT is cleared, which make sure that WDT will not execute, if the code hangs, then the delay will not be executed, the WDT is not cleared, the WDT will count upto its maximum timeout, and sends a reset sequence to the reset register of the micro controller.
*********This code is shown for AT89S52/S51/C51/C52 *********
*********This code is shown for AT89S52/S51/C51/C52 *********
#include<reg51.h>
void delay(unsigned int time)
{
int count=0;
while(count!=time)
{
WDTRST=0x1E;// Clear WDT sequence step1
WDTRST=0xE1; // Clear WDT sequence step2
TMOD=0x01; //16-bit timer0 selected
TH0=0xF8; // Loading high byte in TH
TL0=0xCC; // Loaded low byte in TL
TR0=1; // Running the timer
while(!TF0); //Checking the timer flag register if it is not equal to 1
TR0 = 0; // If TF0=1 stop the timer
TF0 = 0; // Clear the Timer Flag bit for next calculation
count++;
WDTRST=0x1E; // Clear WDT sequence step1
WDTRST=0xE1; // Clear WDT sequence step2
}
}
void main()
{
// initialisations if any
WDTRST=0x1E; // Initilising the WDT step1
WDTRST=0XE1; // Initilising the WDT step2
while(1)
{
//statements
delay(1);
//statements
while(1);
}
--------------------------------------------------------
Expected errors and resolution
"WDTRST" undefined identifier.
"WDTPRG" undefined identifier.
If you see the above error/s while compiling the code, go to the header file and manually add WDTRST=0xA6; and WDTPRG=0xA7; as shown below
Another error Expected the code restarts over and over.
For this make sure that you add more delay(1); statements to clear the WDT where the code is expected not to restart.
How to Test if the WDT is working or not?
Simply add while(1); statement in you code at which stage you want to make the code hang. as shown in the below example
----------------------------------------------------------------
void main()
{
// initialisation if any
WDTRST=0x1E; // Initilising the WDT step1
WDTRST=0XE1; // Initilising the WDT step2
while(1)
{
//statements
delay(1);
//statements
while(1);
}
----------------------------------------------------------------
"WDTPRG" undefined identifier.
void main()
{// initialisation if any
WDTRST=0x1E; // Initilising the WDT step1
WDTRST=0XE1; // Initilising the WDT step2
while(1)
{
//statements
delay(1);
//statements
while(1);
}