CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

WDT and TIMER0 issues on 16F876A

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
webgiorgio



Joined: 02 Oct 2009
Posts: 123
Location: Denmark

View user's profile Send private message

WDT and TIMER0 issues on 16F876A
PostPosted: Fri Jul 08, 2011 2:43 pm     Reply with quote

I think that WDT is resetting the uC too quickly respect to my settings. To avoid the reset I should restart_wdt() at least every 2 seconds (2304 milliseconds).
In my test program there are two leds, a red one is turned ON at the beginning and OFF after a delay which I can change; then, if there is no reset, the green led is blinking every second. On the other hand, if there is a reset I see the red led stable ON.

The problem is that using a delay of just 20ms the reset is already happening! (red led is stable ON). It should not, since reset the WDT within 2000 milliseconds should be enough...

By giving 10 ms delay, the red flashes once very fast and then the green blink every second. (hence there is no watchdog reset).

Code:
#include <16F876A.h>
#fuses XT, PUT, WDT, NOLVP
#use delay(clock = 4000000)
#define green PIN_C5
#define red PIN_B0

int1 flashing;
int8 centisec;

//--------------------------------------------------------------------------
#int_RTCC
void RTCC_isr(void){  //Interrupt Service Routine every 1/100 of second
     set_timer0(98);
     centisec++;
     if (centisec>49){
         centisec=0;
         flashing=!flashing;
     }   
}
//--------------------------------------------------------------------------
void main() {
   setup_wdt(WDT_2304MS);
   set_tris_a(0x3F);
   set_tris_b(0xC8);
   set_tris_c(0x84);
   setup_timer_0 (RTCC_INTERNAL|RTCC_DIV_64);
   enable_interrupts(int_rtcc);
   enable_interrupts(global);   
   
   restart_wdt();
   output_bit(red,1);
   delay_ms(20); //value I change to understand the WDT
   output_bit(red,0);
   while(1){
      output_bit(green,flashing);
      restart_wdt();     
      }
}


Last edited by webgiorgio on Wed Jul 27, 2011 5:25 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19333

View user's profile Send private message

PostPosted: Fri Jul 08, 2011 3:09 pm     Reply with quote

Key is in the data sheet.

On older chips (like the 16F876), the watchdog prescaler is _shared_ with the timer0 prescaler. Look at figure 5.1 in the data sheet. You can have a prescaler for the watchdog, _or_ for timer0, but not both. As soon as you select a prescaler for timer0, the prescaler is _disconnected_ from the watchdog, and the connection goes directly. Selecting a prescaler for timer0, sets the PSA bit to '0', and the watchdog drops to a nominal 18mSec timing (may be as low as 7mSec in some cases....).
Register 5-1. Bit 3.
On most latter chips there is a separate prescaler.

You need to stop using the prescaler for timer0. Better to use another timer for your interrupt (timer2 in particular, since you can program nice decimal counts with this, without trying to reload the timer).

Best Wishes
webgiorgio



Joined: 02 Oct 2009
Posts: 123
Location: Denmark

View user's profile Send private message

PostPosted: Wed Jul 27, 2011 4:59 am     Reply with quote

Hi, thank you for answare.
Can I still use timer0 without prescaler? it would be an interrupt every 255 us, isn't it too often?
It is just a curiosity, I know I can use timer1 and timer2.
webgiorgio



Joined: 02 Oct 2009
Posts: 123
Location: Denmark

View user's profile Send private message

PostPosted: Wed Jul 27, 2011 5:34 am     Reply with quote

I would like to use the watchdog and the interrupt from timer0.
Therefore I do not select prescaler for timer0 (setup_timer_0 (RTCC_INTERNAL); instead of setup_timer_0 (RTCC_INTERNAL | RTCC_DIV_64); )
So the order of the instruction should not make any difference, but it does! (look at the first two rows of my code)

This works:
Code:
   
   setup_timer_0 (RTCC_INTERNAL);
   setup_wdt(WDT_2304MS);
   restart_wdt();
   setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_8 );
   setup_timer_2 (T2_DIV_BY_16,255, 16);   
   enable_interrupts(int_TIMER0);
   enable_interrupts(int_TIMER1);   
   enable_interrupts(int_TIMER2);
   enable_interrupts(global);


while this does not work:
Code:
   
   setup_wdt(WDT_2304MS);   
   setup_timer_0 (RTCC_INTERNAL);
   restart_wdt();
   setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_8 );
   setup_timer_2 (T2_DIV_BY_16,255, 16);   
   enable_interrupts(int_TIMER0);
   enable_interrupts(int_TIMER1);   
   enable_interrupts(int_TIMER2);
   enable_interrupts(global);
Ttelmah



Joined: 11 Mar 2010
Posts: 19333

View user's profile Send private message

PostPosted: Wed Jul 27, 2011 6:23 am     Reply with quote

Yes.
Problem is that setting up a value of '0' for the prescaler, gives division by two, so the prescaler is automatically selected. You have to use:
Code:

   setup_wdt(WDT_2304MS);
   setup_timer_0 (RTCC_INTERNAL | RTCC_DIV_1);

Which then says "don't use the prescaler".

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group