Maker Pro
Maker Pro

How do I make hour-long delay with mid-range PIC?

max_torch

Feb 9, 2014
111
Joined
Feb 9, 2014
Messages
111
I only know how to make short delays. How do I make an hour-long delay used to perform an hourly interrupt (ISR is about transferring data to EEPROM). I am using mid-range PIC or PIC16F628A or PIC16F877A or other similar ones. The timing has to be independent of the main processor. Should I use TMR0, TMR1, or TMR2? Will I need to use a second external crystal oscillator, and will it have to be 32.768KHz?
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,758
Joined
Nov 17, 2011
Messages
13,758
I wouldn't "waste" a timer for this purpose - they aren't meant to be used on that time scale anyway.
Do you have some kind of a clock routine in your code? Then use this to generate a software interrupt (or call to the equivalent subroutine) every hour.
If you don't have a clock routine, make one by using a simple counter that is incremented e.g. every second or millisecond and which triggers the sw-interrupt (or call) when it reaches a count that is equivalent to 1hour (e.g. 3600 seconds).
 

max_torch

Feb 9, 2014
111
Joined
Feb 9, 2014
Messages
111
I don't know how I could make an accurate clocking routine in the main code since the main code is not a consistent repetitive loop, it takes different amounts of time to process the incoming data. I don't know how to embed an accurate counter in the main code in this circumstance, that's why I was thinking if I should use one of the TMR peripherals and have a separate oscillator for it..
The timing of the one hour has to occur while the microcontroller is processing data.
 

Harald Kapp

Moderator
Moderator
Nov 17, 2011
13,758
Joined
Nov 17, 2011
Messages
13,758
I don't know how I could make an accurate clocking routine in the main code since the main code is not a consistent repetitive loop
You don't have to.
Use a timer to create e.g. a millisecond interrupt, then count milliseconds. Reset the millisecond counter when it has reached 3600000 ant the 1hour interrupt (or subroutine call) has been activated.
 

Sadlercomfort

Ash
Feb 9, 2013
424
Joined
Feb 9, 2013
Messages
424
You need to create a timer0 interrupt routine of 60 seconds. Then your subroutine for the interrupt should include a count variable, which counts to 60 (60s x 60 = 1 hour).

To do this you need to work out the value of TMR0 using this formula:
Freq. out = Freq. osc / [prescaler * (256 - TMR0) * count]


Simply rearrange to make TMR0 the subject.





Here's a basic example which flashes an LED.


Code:
volatile char counter = 0;

void interrupt Timer0_ISR(void)
{
    if (counter ==16)
    {
    goto flash_led;
    }
    counter++;
    return;
     

flash_led:
//Set LED HIGH
return; 
}


void main(void)
{
ADCON1 = 0b00000111;
TRISA=0b00000000;
TRISB=0b00000001;            //Initialise I/O ports  (RB0 set as output)
TRISC=0b00000000;          //Initialise I/O ports
PORTA=0b00000000;
PORTB=0b10000000;          //Initialise I/O ports
                   
TMR0=6;
OPTION_REG=0b01000000;    //Enable Rising Edge Trigger
TMR0IE=1;                       //Enable TMR0 Overflow Interruprt
GIE=1;                           //Enable Global Interrupt



    while(1)
    {
    }
}
 
Top