ad space

PIC16F877A Timers Explained: Understanding and Using Timers in Embedded Projects

 Timers are essential components in microcontroller-based projects, as they allow for precise timekeeping and event scheduling without the need for manual delays, which can block other processes. The PIC16F877A microcontroller has three timers—Timer0, Timer1, and Timer2—each offering different features for a variety of applications. In this post, we will break down the working principles of each timer and provide example code to show how they can be used in real-world embedded projects.


Overview of PIC16F877A Timers

  1. Timer0:

    • 8-bit timer.
    • Can be configured as a counter (counts external events) or a timer (counts internal clock cycles).
    • Can generate interrupts.
  2. Timer1:

    • 16-bit timer.
    • Can operate as a timer or counter.
    • Can be used for external event counting or clock generation.
  3. Timer2:

    • 8-bit timer with a built-in prescaler and postscaler.
    • Primarily used for generating Pulse Width Modulation (PWM) signals.

Timer Configuration Basics

Each timer has configurable prescaler values, which divide the clock to control how fast the timer counts. You can also configure the timer to generate an interrupt when it overflows (reaches its maximum value and resets to 0), allowing you to execute code at specific intervals.

Key Registers for Timers:

  • TMR0, TMR1H
    , TMR2
    : Timer registers that hold the current count value.
  • T0CON, T1CON, T2CON: Control registers that configure the timers.
  • INTCON, PIE1: Interrupt control registers used to enable/disable timer interrupts.

Example 1: Using Timer0 to Create Delays

Let’s configure Timer0 to generate a 1-second delay.

Steps:

  1. Set the timer mode (internal clock).
  2. Choose the appropriate prescaler.
  3. Calculate the value to preload the timer for a 1-second overflow.
  4. Enable the Timer0 interrupt.

Example Code:

#define _XTAL_FREQ 16000000 // 16 MHz Crystal Oscillator

#include <xc.h>

// CONFIGURATION BITS
#pragma config FOSC = HS // High-speed oscillator
#pragma config WDTE = OFF // Disable Watchdog Timer
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF

// Global flag to indicate the timer overflow
volatile int timerOverflow = 0;

// Interrupt service routine
void __interrupt() ISR() {
if (T0IF) { // Timer0 overflow flag
T0IF = 0; // Clear the overflow flag
TMR0 = 60; // Reload the timer to count for the next cycle
timerOverflow++; // Increment overflow count
}
}

void Timer0_Init() {
T0CS = 0; // Use internal clock (Fosc/4)
PSA = 0; // Assign prescaler to Timer0
PS2 = 1; PS1 = 1; PS0 = 1; // Prescaler set to 256
TMR0 = 60; // Preload TMR0 for approximately 1 second overflow
T0IE = 1; // Enable Timer0 interrupt
GIE = 1; // Enable global interrupts
}

void main() {
TRISB = 0x00; // Set PORTB as output for LED
Timer0_Init(); // Initialize Timer0

while (1) {
if (timerOverflow >= 61) { // 61 overflows give approximately 1 second
PORTB ^= 0x01; // Toggle RB0 (LED)
timerOverflow = 0; // Reset the counter
}
}
}

Explanation:

  • We configure Timer0 in timer mode with a prescaler of 256. The 8-bit timer overflows every ~16 ms, so 61 overflows give approximately 1 second.
  • The TMR0 register is preloaded with 60 to adjust the timing for a 1-second delay.
  • PORTB is used to toggle an LED connected to pin RB0.

Circuit Diagram

led blink with timer circuit diagram



Example 2: Using Timer1 for External Event Counting

Timer1 can be used to count external pulses. For instance, we could connect a switch to count how many times the button is pressed.

Steps:

  1. Set Timer1 to counter mode.
  2. Configure the external pin.
  3. Display the count on an LED or LCD.

Example Code:

#include <xc.h>

#define _XTAL_FREQ 16000000

// CONFIGURATION BITS
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF

void Timer1_Init() {
T1CON = 0x01; // Enable Timer1, no prescaler
TMR1H = 0; // Clear high byte
TMR1L = 0; // Clear low byte
}

void main() {
TRISC = 0xFF; // Configure PORTC as input for external event counting
TRISB = 0x00; // Configure PORTB as output for displaying count

Timer1_Init(); // Initialize Timer1 in counter mode

while (1) {
PORTB = TMR1L; // Display lower 8 bits of count on PORTB (LEDs)
}
}


Explanation:

  • Timer1 is configured in counter mode and connected to an external pin that will increment the counter for each pulse received.
  • The current count is displayed on PORTB, where LEDs are connected to visualize the count.

Timer1 for External Event Counting


Example 3: Generating a PWM Signal Using Timer2

Timer2 is often used to generate PWM signals, useful in controlling motor speed, brightness of LEDs, etc.

Steps:

  1. Set Timer2 to PWM mode.
  2. Configure the PWM duty cycle and frequency.
  3. Output the PWM signal on a designated pin.

Example Code:

#include <xc.h>

#define _XTAL_FREQ 16000000

void Timer2_Init() {
T2CON = 0x04; // Enable Timer2 with a prescaler of 1
PR2 = 255; // Set PWM period (8-bit)
CCPR1L = 128; // Set duty cycle to 50%
CCP1CON = 0x0C; // Configure CCP1 module for PWM mode
TRISC2 = 0; // Set RC2 as output for PWM
}

void main() {
Timer2_Init(); // Initialize Timer2 for PWM

while (1) {
// PWM signal is generated on RC2
}
}


Explanation:

  • Timer2 is set up to generate a PWM signal on RC2.
  • The PWM duty cycle is set to 50%, meaning the output signal is HIGH for half the period and LOW for the other half.

PWM Signal Using Timer2


Conclusion

Timers in the PIC16F877A provide versatile tools for handling time-based tasks such as creating delays, counting external events, and generating PWM signals. By understanding how to configure and use each timer, you can enhance the functionality of your embedded projects. Whether you need accurate delays or precise event scheduling, timers are indispensable components for any microcontroller-based system.

Further Reading:

Post a Comment

Previous Post Next Post