Monday, November 28, 2016

Watch dog timer on 8051 using AT89S52, Tested and working

Watchdog Timer in 8051, Tested and working code 

What is watch Dog timer:

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. 

Image result for what is watch dog timer

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)
---------------------------------------------------------------

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);
}
--------------------------------------------------------

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);

}
----------------------------------------------------------------
The Code hangs at while(1); If the WDT is executed successfully then it restart the code ,and you will see the below statement in the output window of keil compiler.