View previous topic :: View next topic |
Author |
Message |
lemmy
Joined: 26 Sep 2012 Posts: 4
|
WDT and Sleep |
Posted: Wed Sep 26, 2012 8:32 am |
|
|
I am fairly new to PIC devices so please forgive any stupid questions! I am trying to write code that sets the WDT to software control, and then turns on the WDT, then goes to sleep, then wakes up, toggles an output line, then goes back to sleep, then repeating this indefinitely. I had this code working, but for some reason it isn't anymore and I can't figure out what I changed. I am using the F1 Eval board with the PIC16LF1937 device. This is the code I have
Code: | //main.c
#include "16LF1937.h"
#fuses WDT_SW
void main ()
{
int x;
setup_oscillator(OSC_125KHZ);
setup_wdt(WDT_2S);
while(1)
{
sleep();
x++;
output_toggle(PIN_D1);
}
} |
I know the board is working because I have some other code I wrote that toggles the same line but doesn't go to sleep (I use a delay_ms command to space out the toggles). I have tried debugging the code while single stepping through but it fails on the "sleep();" command. I am using the PickKit3 and I get "Pk3Err0031:Failed to get PC" error when the single step tries to execute the sleep. If I take the sleep command out, it runs fine (and the debugger steps through it fine), but of course the line toggles at a very fast rate.
I have looked at the registers as I step through and I have looked at the dissasembly listing and the SWDTEN bit is being set properly so the WDT should be enabled. The WDTCON register contents change from 0x16 to 0x19 (which is WDTPS = 01100 for 1:131072 = 4S and SWDTEN = 1). What am I doing wrong? I had this working fine at one point. Thanks for any suggestions.
My compiler version is "CCS PCM C Compiler, Version 4.135, 4787 " |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Wed Sep 26, 2012 8:57 am |
|
|
The obvious thing is that the debugger _cannot debug the watchdog_. The processor clock needs to be running for the debugger to work, and when you use sleep, this stops.
This is what the break on sleep option in the debugger is 'for', allowing you to stop at the point where you want to trigger a sleep.
This is also why, if you use MPLAB, and select the DEBUG option, it'll turn the watchdog fuse off.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
lemmy
Joined: 26 Sep 2012 Posts: 4
|
|
Posted: Wed Sep 26, 2012 9:17 am |
|
|
Thanks for your help. The problem was that Debug was still selected instead of "Release" even when I was not debugging. I changed that and it is working fine. Thanks again! |
|
![](templates/subSilver/images/spacer.gif) |
lemmy
Joined: 26 Sep 2012 Posts: 4
|
|
Posted: Wed Sep 26, 2012 11:37 am |
|
|
I have one other question regarding waking from sleep. I know that the WDT will wake the device from sleep, and also "any external interrupt". Does that include the "interrupt on change" pins on port B or is it just the INT pin (RB0)? I am pretty sure it does, but the reason I ask is that this isn't working quite right
Code: | #include "16LF1937.h"
#fuses WDT_SW
void main ()
{
int x;
setup_oscillator(OSC_125KHZ);
enable_interrupts(INT_RB2_H2L);
sleep();
x++;
setup_wdt(WDT_1S);
while(1)
{
sleep();
x++;
output_toggle(PIN_D1);
}
} |
I would expect it to start and then immediately go to sleep (after setting up the RB2 interrupt of course). Then when RB2 goes from H to L I would think it would wake from sleep, start the WDT with 1s interval, and then enter the While loop and wake every 1 second and toggle pin D1. If I take out the first sleep(); it does toggle every one second. But if I leave it in, I get a 1 second high on D1 every time I change RB2 from H to L or from L to H. Otherwise it is always off.
If I simply use the external INT line (RB0) instead of RB2 Interrupt on Change then it works exactly like I expect it to. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Wed Sep 26, 2012 2:39 pm |
|
|
With interrupt on change, you have to read the port, to reset the 'change' latch. It can also get set during boot.
So you need to read the pin on portB, clear the interrupt, then call sleep.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
lemmy
Joined: 26 Sep 2012 Posts: 4
|
|
Posted: Thu Sep 27, 2012 7:27 am |
|
|
Ok. Thanks, I will try that. |
|
![](templates/subSilver/images/spacer.gif) |
|