nerdegutta.no
PIC16F690 - Day 4: Introduction to Timers(Timer0)
09.08.25
Embedded
Goal:Learn to generate accurate delays using Timer0, comparing it with software delays.
Timer0 is an 8-bit timer with optional prescaler and interrupt support.
We'll blink an LED every ~500 ms using:
Software loop delay (baseline)
Timer0 overflow + interrupt
Hardware: LED on RB0
Concepts:
Timer0 = 8-bit counter (0–255), overflow triggers interrupt
Prescaler divides clock to slow counting
With 4 MHz clock: 1 instruction = 1 μs (since Fosc/4 = 1 MHz)
Code 1: Software Delay for LED Blink (baseline)
#define _XTAL_FREQ 4000000 #include < xc.h > // Remove extra space // CONFIG #pragma config FOSC = INTRCIO #pragma config WDTE = OFF #pragma config PWRTE = OFF #pragma config MCLRE = OFF #pragma config BOREN = OFF #pragma config CP = OFF #pragma config CPD = OFF void main(void) { TRISB0 = 0; // RB0 as output ANSEL = 0; ANSELH = 0; while (1) { RB0 = 1; __delay_ms(500); RB0 = 0; __delay_ms(500); } }Code 2: Blink using Timer0 Overflow Interrupt
#define _XTAL_FREQ 4000000 #include < xc.h > // remove extra spaces #include < stdint.h > // remove extra spaces // CONFIG #pragma config FOSC = INTRCIO #pragma config WDTE = OFF #pragma config PWRTE = OFF #pragma config MCLRE = OFF #pragma config BOREN = OFF #pragma config CP = OFF #pragma config CPD = OFF volatile uint8_t overflow_count = 0; void __interrupt() isr(void) { if (T0IF) { T0IF = 0; // Clear interrupt flag overflow_count++; if (overflow_count >= 8) { RB0 = !RB0; // Toggle LED overflow_count = 0; } } } void main(void) { TRISB0 = 0; ANSEL = 0; ANSELH = 0; PORTB = 0; OPTION_REGbits.T0CS = 0; // Timer0 uses internal clock OPTION_REGbits.PSA = 0; // Prescaler assigned to Timer0 OPTION_REGbits.PS = 0b111; // 1:256 prescaler TMR0 = 0; T0IE = 1; // Enable Timer0 interrupt GIE = 1; // Enable global interrupts while (1) { // Main loop idle; Timer0 handles LED blinking } }