Nerdegutta's logo

nerdegutta.no

PIC 16F688 - 1 sec interrupt demo

26.12.23

Embedded

The 1-sec.

This is a small demo on how to use interrupt to flash a led at a 1 sec rate.

PIC16F688 have one 8-bit timer. This means that the max value TMR0 can have is 256, then it rolls over to 0, creating an interrupt.

To generate a one sec delay interval, the timer should count 1 000 000 machine cycles. If we use the prescaler value of 256, the required count will be reduced to 3906. So, if we preload the TMR0 with 39, it will overflow after 256-39 = 217 counts. This gives the required number of overflows to make 3906 counts:

3906 / 217 = 18,

with this setting, after every 18 overflow of TMR0 register, which is preloaded with 39, an appx 1 sec interval is elapsed.

#include 

// CONFIG
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Detect (BOR enabled)
#pragma config IESO = ON        // Internal External Switchover bit (Internal External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)

#define _XTAL_FREQ 8000000      // Reference for compiler
#define led PORTCbits.RC3       // LED is connected to this pin)

volatile unsigned char num;     // Variable has to be volatile, for the interrupt func to be able to write

void __interrupt() ISR(void) {  // We've had an interrupt
    num++;                      // Increase num by one
    if (num == 18) {            // If num is 18 -> 18 inpterrupts
        led = ~led;             // Toggle LED
        num = 0;                // Reset num varialbe
    }
    TMR0 = 39;                  // Set TMR0 to 39.
    INTCONbits.T0IF = 0;        // Timer0 Overflow interrupt flag is cleared
}

void main(void) {
    CMCON0      = 0x07;         // Disable comparators
    ANSEL       = 0b00000000;   // Disable analog channles
    TRISC       = 0b00000000;   // Set PORTC to output
    led         = 0;            // Set led to LOW
    num         = 0;            // Set num to 0
    OPTION_REG  = 0b00000111;   // Prescaler set to 1:256 // 0x07;
    TMR0        = 39;           // Preload TMR0 with 39
    INTCON  = 0b10100000;       // GIE = 1, PEIE = 0, T0IE = 1, or 0xA0;
    do {

    }while (1);
}