Maker Pro
Maker Pro

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

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
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).
 
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
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.
 
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