|
|
View previous topic :: View next topic |
Author |
Message |
zamzam23
Joined: 25 Aug 2010 Posts: 47
|
wdt with timer0 interrupt with 18f46k22 |
Posted: Tue Jun 11, 2019 7:27 am |
|
|
hi,
I have used wdt clearly but I couldn't use wdt with timer0 interrupt.
(I want to write message on lcd before reset the card).
I use this code but not working.
Code: |
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_1);
setup_wdt(WDT_ON | WDT_1S);
|
How can I use interrupt with wdt?
thanks. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jun 11, 2019 9:34 am |
|
|
Post a complete (but small) test program, where you enable interrupts
and have a Timer0 interrupt routine.
Also post your compiler version.
The reason is, in the 18F46K22, according to the block diagrams in the
data sheet, there is no connection between Timer0 and WDT.
In older PICs, like the 16F877, yes.
If you post a real test program, we can see what you're doing. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Tue Jun 11, 2019 10:31 am |
|
|
However even on the older PIC's, the only 'connection' is that the prescaler
is shared. The two systems are otherwise independant, and enabling the
watchdog does not affect the ability to use timer0 at all. |
|
|
zamzam23
Joined: 25 Aug 2010 Posts: 47
|
|
Posted: Wed Jun 12, 2019 1:46 am |
|
|
of course, here is some part of code. (Complier: v5.055)
Code: |
#ignore_warnings 203
#include "18f46K22.h"
#DEVICE *=16,PASS_STRINGS=IN_RAM, HIGH_INTS=TRUE
#ROM int16 getenv("EEPROM_ADDRESS") = {500}
#device ADC=10
#include "stdlib.h"
#include "math.h"
#fuses HSH,WDT_SW,NOBROWNOUT,NOLVP,PUT,NOWRT,NODEBUG,NOCPD,NOSTVREN,NOPROTECT,NOIESO,NOFCMEN,NOPLLEN
#use delay(crystal=20MHz, clock=20Mhz)
#int_rtcc
void interrupt_wdt(void)
{
glcd_init(on); delay_ms(50);
glcd_text57(5,20,"WDT alarm is coming!",1,on);
while(1);
}
#use delay(clock=20M)
void main ( )
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
disable_interrupts(INT_TIMER1);
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(sAN0 | sAN1);
delay_us(25);
setup_timer_2(T2_DISABLED,0,1);
setup_ccp1(CCP_OFF);
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_1);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
setup_wdt(WDT_ON | WDT_1S);
while(1)
{
restart_wdt();
}
} |
|
|
|
zamzam23
Joined: 25 Aug 2010 Posts: 47
|
|
Posted: Wed Jun 12, 2019 4:44 am |
|
|
PCM programmer wrote: |
The reason is, in the 18F46K22, according to the block diagrams in the
data sheet, there is no connection between Timer0 and WDT.
In older PICs, like the 16F877, yes.
|
if there is no connection between wdt and timer0, this code will not work as normally right?
So, how can I get alarm just before wdt reset? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Wed Jun 12, 2019 5:31 am |
|
|
It's not really possible. The WDT is not xtal contolled and basic timing for it is 3.5-4.7ms from the data sheet. This will be at 'room temperature' and will vary on actual temperature.
Now you could add an EXTERNAL WDT(E-WDT).Old school was to use a 74123(?) retriggerable multivibrator that would send a constant 'high' until it timed out, to an interrupt input pin. 'main()' would send a pulse to the E-WDT. Keep in mind this device is R-C timed as well, so it'll vary.
What is the purpose for using the WDT ?
also...
having ANY delays inside any ISR is bad coding |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Wed Jun 12, 2019 5:39 am |
|
|
The units are never connected. The only 'link' is that on some of the more
basic PIC's they share their prescaler.
On this chip, two completely separate units. You are setting the watchdog
for a nominal 1 second (beware you should restart the watchdog before doing
this otherwise it may well have counted quite a few cycles already at this
point - changing the divisor does not reset the count). Then a separate timer
being fed off the master oscillator, /4 /1 /65536, so 1/76th second.
Then, how are you testing?. Understand that the WDT, will not function
in a debugger.
Then the watchdog, does not actually start running till you get into the
timer0 interrupt code, since you have a restart_wdt in the main code.
So it'll enter this timer interrupt after 1/76th second, then wait for (about) 1
second, till the watchdog fires. The code as posted can't compile, since you
don't load any code for the GLCD.
Some comments inline:
Code: |
#include "18f46K22.h"
//*=16 not required on a PIC18
//You are also not using HIGH_INTS
#DEVICE PASS_STRINGS=IN_RAM
#ROM int16 getenv("EEPROM_ADDRESS") = {500}
#device ADC=10
#fuses HSH,WDT_SW,NOBROWNOUT,NOLVP,PUT,NOWRT,NODEBUG,NOCPD,NOSTVREN,NOPROTECT,NOIESO,NOFCMEN,NOPLLEN
#use delay(crystal=20MHz, clock=20Mhz)
//code should always be after fuses and clock
#include <stdlib.h>
#include <math.h>
//Don't switch netween using RTCC and Timer0
#INT_TIMER0
void interrupt_timer0(void)
{
//You don't show any driver for the GLCD being loaded
glcd_init(on); delay_ms(50);
glcd_text57(5,20,"WDT alarm is coming!",1,on);
//If you use 'TRUE', you don't need to ignore warning 203
while(TRUE)
; //Now because the code will stall here, the watchdog will trigger
}
#use delay(clock=20M)
void main ( )
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
//ADC_CLOCK_INTERNAL is not recommended above 1MHz
setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports(sAN0 | sAN1);
delay_us(25);
setup_timer_2(T2_DISABLED,0,1);
setup_ccp1(CCP_OFF);
setup_timer_0(T0_INTERNAL | T0_DIV_1);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
setup_wdt(WDT_ON | WDT_1S);
while(TRUE)
{
restart_wdt();
}
}
|
The timer, and the watchdog are two separate systems. |
|
|
zamzam23
Joined: 25 Aug 2010 Posts: 47
|
|
Posted: Wed Jun 12, 2019 7:10 am |
|
|
thanks for your explanatory answers.
I understood that wdt and timerX are separate systems so I am going to think another way for progress my software.
I cannot detect wdt just before triggers but Maybe I can detect it just after wdt with this code.
Code: | switch ( restart_cause() )
{
case WDT_TIMEOUT:
{
glcd_text57(5,20,"WDT reset !...",1,on);
delay_ms(2000);
break;
}
case NORMAL_POWER_UP:
{
break;
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Wed Jun 12, 2019 7:23 am |
|
|
Though the systems are independant, there is no reason at all that you cannot
set a timer to actually trigger just before the watchdog.
However remember that sending text to a GLCD, will take a significant
time, so you need to allow for this. Also the watchdog won't trigger while
the code is looping calling restart_wdt.
So:
Code: |
void main ( )
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
//ADC_CLOCK_INTERNAL is not recommended above 1MHz
setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports(sAN0 | sAN1);
delay_us(25);
setup_timer_2(T2_DISABLED,0,1);
setup_ccp1(CCP_OFF);
setup_timer_0(T0_INTERNAL | T0_DIV_64);
set_timer0(0L);
//This now gives 20MHz/(4*16*65536) = 1.19Hz
//So interrupt in 0.838 seconds
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
setup_wdt(WDT_ON | WDT_1S);
restart_wdt();
while(TRUE)
{
delay_cycles(1);
//Now code will sit here, and the timer will trigger in 0.838
//seconds and the watchdog a few mSec later.
}
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Thu Jun 13, 2019 4:33 am |
|
|
re:
Quote: | I am going to think another way for progress my software. | Please tell us what you're trying to do, we may know of a way to do it.
You need to remember the WDT is not an accurate 'timer'.
Jay |
|
|
|
|
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
|