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
}
}