View previous topic :: View next topic |
Author |
Message |
embedder
Joined: 11 Feb 2010 Posts: 19
|
Software control of WDT on PIC18F87K22 |
Posted: Tue Nov 08, 2011 5:47 pm |
|
|
PCH 4.125
I am trying to enable/disable the PIC18F87K22 WDT under software control. I've read the few posts that there are here and the help files, and the fuse definitions but no luck.
The help for setup_wdt() says:
"For PCH parts .... with software controlled WDT, setup_wdt( ) would enable/disable watchdog timer only if NOWDT fuse is set."
So I have set-up my WD like this:
Code: | #fuses NOWDT
#fuses WDT1024
#fuses WDT_SW
setup_wdt(WDT_ON);
|
But: Code: | setup_wdt(WDT_OFF); | has no effect
The NOWDT fuse setting seems to contradict some other posts here, but it too has no effect either way.
Am I missing something obvious? Thanks. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 08, 2011 6:50 pm |
|
|
This thread discusses turning on the WDT under software control, and
it has code to demonstrate this:
http://www.ccsinfo.com/forum/viewtopic.php?t=45439
Can you post a small program that shows how you turn off the WDT,
and how it fails ? Post a program that demonstrates the failure mode. |
|
|
embedder
Joined: 11 Feb 2010 Posts: 19
|
|
Posted: Wed Nov 09, 2011 7:55 am |
|
|
Thanks PCM programmer. I read and followed that thread, but it doesn't show the WD being successfully turned off - that's one of the problems highlighted. I will post some code. |
|
|
embedder
Joined: 11 Feb 2010 Posts: 19
|
|
Posted: Wed Nov 09, 2011 10:19 am |
|
|
OK, here's some code.
After setup_wdt(WDT_OFF) the LED should stay on for 8 seconds, then off for 1 sec, then back on and finally the WD should cause a reset after 4 seconds. However, the PIC is always reset by the WD after 4 sec. From the visible flutter of the LED the "reason" is a WDT_TIMEOUT every time after the initial power-up.
Is setup_wdt(WDT_OFF) intended to be used to disable the WD in this scenario?
Code: | #include <18F87K22.h>
// *** Watchdog Timer *** //
// WDT resolution = 4ms
// WDT post-scalers = 256 512, 1024 2048 4096 8192 16384 32768
// WDT time-outs = 1.024 2.048 4.096 8.192 16.384 32.768 65.536 131.027 sec
#FUSES WDT1024 // WDT = 1024 * 4 ms = 4.0960 sec.
#FUSES WDT_SW // WDT is s/w controlled
#FUSES WDT_NOSLEEP // WD disabled during sleep
#FUSES NOPLLEN
//#use delay(internal=64mhz)
#use delay(internal=16mhz)
void main()
{
//setup_oscillator(OSC_16MHZ | OSC_PLL_ON); // Fosc = 64 MHz
setup_oscillator(OSC_16MHZ); // Fosc = 16 MHz
int8 i, reason;
reason = restart_cause();
if(reason==WDT_TIMEOUT){
for(i=0;i<3;i++){
output_high(PIN_A4); // LED on
delay_ms(30);
output_low(PIN_A4); // LED off
delay_ms(30);
}
}
setup_wdt(WDT_OFF); // Disable WDT.
output_low(PIN_A4); // LED off
delay_ms(1000); // Wait one second
output_high(PIN_A4); // LED on
delay_ms(8000); // Wait eight seconds. WD should not bark
output_low(PIN_A4); // LED off
delay_ms(1000); // Wait one second
output_high(PIN_A4); // LED on
setup_wdt(WDT_ON); // Enable WDT. It will reset in 4 seconds.
while(1);
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Nov 09, 2011 2:22 pm |
|
|
I made a better test program. I didn't like your LED stuff because it
didn't give me enough information, etc. The program below displays
the reason for the restart. Then it turns on the WDT and waits in a
getc() loop. If you don't press a key, it will do a WDT timeout while
in that loop. (The loop is in the internal code for getc). If you do
press a key, then the WDT is turned off, and it will tell you this.
For this test, I programmed the PIC and then unplugged the DC power
cord and the ICD2 from the board. Then I plugged in the power and
I got this output. I didn't press a key for several seconds, to prove that
it's restarting due to a WDT timeout. Then I pressed Enter and no more
WDT timeouts. So this shows that it's working:
Quote: |
Normal power up
Press any key within 4 seconds to turn off the WDT
Restart because of WDT timeout
Press any key within 4 seconds to turn off the WDT
Restart because of WDT timeout
Press any key within 4 seconds to turn off the WDT
Restart because of WDT timeout
Press any key within 4 seconds to turn off the WDT
WDT disabled. Nothing more should print.
|
I don't have your exact PIC, but it's similar. It's in the K22 series.
I tested this with compiler vs. 4.125.
Code: |
#include <18F45K22.h>
#fuses INTRC_IO, WDT_SW, WDT1024, NOPLLEN, NOPBADEN
#use delay(clock=4M)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//===================================
void main()
{
switch(restart_cause())
{
case WDT_TIMEOUT:
{
printf("Restart because of WDT timeout \n\r");
break;
}
case NORMAL_POWER_UP:
{
printf("Normal power up \n\r");
break;
}
}
setup_wdt(WDT_ON);
printf("Press any key within 4 seconds to turn off the WDT \r\n");
getc();
setup_wdt(WDT_OFF);
printf("WDT disabled. Nothing more should print. \n\r");
while(1);
} |
|
|
|
embedder
Joined: 11 Feb 2010 Posts: 19
|
|
Posted: Wed Nov 09, 2011 3:24 pm |
|
|
There is one essential difference between your code and mine, and it turns out to be the answer:
This fuse disables s/w control of the WD.
I don't know if it is meant too, but I can just manually turn-off/on the WD prior to going to sleep and waking-up.
Thanks for your help. |
|
|
embedder
Joined: 11 Feb 2010 Posts: 19
|
|
Posted: Wed Nov 09, 2011 3:35 pm |
|
|
Page 419 of the datasheet seems to mean that there are four mutually exclusive WD modes. i.e. Setting fuse WDT_NOSLEEP after fuse WDT_SW changes the mode to h/w enabled (but disabled when asleep)
The WDT can be operated in one of four modes as
determined by CONFIG2H<WDTEN<1:0> The four
modes are:
• WDT Enabled
• WDT Disabled
• WDT under software control,
- SWDTEN (WDTCON<0>)
• WDT
- Enabled during normal operation
- Disabled during Sleep |
|
|
|