PIC16F877 Timer: A Comprehensive Guide to Timer Modules

by Marwen Maghrebi

The PIC16F877 Timer is a vital component for achieving precise timing and event control in microcontroller projects.

Features of the PIC16F877 Timer project in Proteus simulation.

Things used in this project

Software apps and online services:

1- MPLAB

2- Proteus 8

Enhancing Embedded Systems with Timer-Based LED Control

In the realm of embedded systems, leveraging the PIC16F877 TIMER for LED control presents not only an efficient but also a versatile approach to manage visual feedback and signaling within various applications. By harnessing the capabilities of the PIC16F877 TIMER, developers can implement precise timing intervals for LED blinking. Consequently, this enhances the functionality and user experience of their embedded systems.

Timer-Based LED Control:

In the realm of embedded systems, leveraging timers for LED control presents an efficient and versatile approach to manage visual feedback and signaling within various applications. By harnessing the capabilities of timers, developers can implement precise timing intervals for LED blinking, thereby enhancing the functionality and user experience of their embedded systems.

Key Benefits:

Precision Timing: First and foremost, timer modules offer a high degree of precision in generating time intervals, ensuring consistent and accurate LED blinking patterns.

Resource Efficiency: Moreover, by offloading the timing control to dedicated timer modules, developers can optimize resource utilization within the microcontroller. As a result, the main program can focus on other tasks without being burdened by timing functions.

Flexibility: In addition, timer-based LED control provides developers with the flexibility to define blinking frequencies and patterns, catering to the specific requirements of their applications.

Applications:

  • Indication and Signaling: Timer-controlled LEDs are commonly used for indication and signaling purposes in various embedded systems, such as alarm systems, status indicators, and user interfaces.
  • Communication: Blinking LEDs can also serve as a means of communication, conveying information or feedback to users in a visual format. For example, different blinking patterns may signify different system states or error conditions.
  • Aesthetics: In applications where aesthetics play a crucial role, such as consumer electronics and automotive displays, timer-based LED control allows developers to create visually appealing lighting effects and animations.

Implementation Considerations::

  • Timer Configuration: Developers must configure timer modules with appropriate prescaler values and period registers to achieve the desired blinking frequency.
  • Interrupt Handling: Proper handling of timer interrupts is essential to ensure timely execution of LED control routines without disrupting the normal operation of the microcontroller.
  • Power Consumption: Careful consideration should be given to power consumption, especially in battery-powered applications, by optimizing the blinking frequency and duty cycle of LEDs to minimize energy consumption.

Project Name: Timer-Based LED Toggler with UART Monitoring

This code initializes multiple interrupt counters and toggles LEDs connected to different pins of the PIC16F877A microcontroller based on specific time intervals. Additionally, it implements UART communication to send a message periodically via serial transmission. Below is the breakdown of the code:

Code (in C using XC8 Compiler):

Configuration and Initialization

This section includes the necessary configuration settings, global variables, and the initialization of the UART module. It sets up the microcontroller’s configuration bits, defines the system clock frequency, and prepares the UART communication for serial data transmission.

/*
 * File: main.c
 * Author: Marwen Maghrebi
 * Description:
 * Timer-based LED toggling with UART monitoring.
 * This code initializes multiple interrupt counters and toggles LEDs connected to different pins of 
 * the PIC16F877A microcontroller based on specific time intervals. Additionally, it implements UART 
 * communication to send a message periodically via serial transmission.
 */

#include <xc.h>
#include <stdint.h>
#include <stdio.h>

// Configuration bits (assuming a PIC16F877A microcontroller)
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config BOREN = ON
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config DEBUG = OFF

// Define the system clock frequency
#define _XTAL_FREQ 8000000 // 8 MHz

// Global variables for the interrupt counts
volatile uint8_t interrupt_count1 = 0;
volatile uint16_t interrupt_count2 = 0;
volatile uint16_t interrupt_count3 = 0;
volatile uint16_t interrupt_count4 = 0;
volatile uint16_t interrupt_count5 = 0;

// UART initialization function
void UART_Init(void) {
    TRISC6 = 0; // TX pin set as output
    TRISC7 = 1; // RX pin set as input

    TXSTAbits.SYNC = 0;  // Asynchronous mode
    TXSTAbits.BRGH = 1;  // High-speed mode

    SPBRG = 51; // Baud rate 9600 for 8 MHz clock

    RCSTAbits.SPEN = 1;  // Enable serial port
    TXSTAbits.TXEN = 1;  // Enable transmission
}

UART Transmission Functions and Interrupt Service Routine (ISR)

This section contains the UART transmission functions to send data via serial communication. It also includes the ISR that handles the Timer2 overflow interrupt, toggling the LEDs based on the defined time intervals.

// UART transmit function
void UART_Transmit(char data) {
    while (!TXIF); // Wait until the transmit buffer is empty
    TXREG = data;  // Transmit the data
}

// UART send string function
void UART_SendString(const char *str) {
    while (*str) {
        UART_Transmit(*str++);
    }
}

void __interrupt() ISR() {
    if (TMR2IF) { // Check if Timer2 overflow interrupt flag is set
        TMR2IF = 0; // Clear the interrupt flag
        
        // Increment the interrupt counts
        interrupt_count1++;
        interrupt_count2++;
        interrupt_count3++;
        interrupt_count4++;
        interrupt_count5++;
        
        // Toggle LEDs based on the specified intervals
        if (interrupt_count1 >= 100) { // 10 seconds (assuming 100 ms overflow time)
            PORTBbits.RB0 ^= 1; // Toggle LED on RB0
            interrupt_count1 = 0;
        }
        if (interrupt_count2 >= 200) { // 20 seconds
            PORTBbits.RB1 ^= 1; // Toggle LED on RB1
            interrupt_count2 = 0;
        }
        if (interrupt_count3 >= 300) { // 30 seconds
            PORTBbits.RB2 ^= 1; // Toggle LED on RB2
            interrupt_count3 = 0;
        }
        if (interrupt_count4 >= 400) { // 40 seconds
            PORTBbits.RB3 ^= 1; // Toggle LED on RB3
            interrupt_count4 = 0;
        }
    }
}

Main Function and Loop

This section includes the main function where the microcontroller is configured. It initializes the Timer2 and enters the infinite loop that periodically sends messages via UART, allowing monitoring of the loop execution.

void main(void) {
    // Configure RB0, RB1, RB2, and RB3 as output
    TRISBbits.TRISB0 = 0;
    TRISBbits.TRISB1 = 0;
    TRISBbits.TRISB2 = 0;
    TRISBbits.TRISB3 = 0;
    
    // Turn off LEDs initially
    PORTBbits.RB0 = 0;
    PORTBbits.RB1 = 0;
    PORTBbits.RB2 = 0;
    PORTBbits.RB3 = 0;

    // Configure Timer2
    T2CONbits.T2CKPS = 0b11; // Prescaler 1:16
    PR2 = 124; // Load Period Register (PR2)
    TMR2 = 0; // Clear Timer2 register
    T2CONbits.TMR2ON = 1; // Turn on Timer2

    // Enable Timer2 interrupt
    PIE1bits.TMR2IE = 1; // Enable Timer2 interrupt
    INTCONbits.PEIE = 1; // Enable peripheral interrupts
    INTCONbits.GIE = 1; // Enable global interrupts

    // Initialize UART
    UART_Init();

    uint32_t loop_counter = 0;
    char buffer[32];

    while (1) {
        // Increment loop counter
        loop_counter++;
        
        // Create the message string
        sprintf(buffer, "LOOP EXECUTE %lu\r\n", loop_counter);
        
        // Send the message via UART
        UART_SendString(buffer);
        
        // Delay to prevent flooding the UART
        __delay_ms(1000);
    }
}

Proteus Configuration :

  • Open Proteus & Create New Project and click next

  • Click on Pick Device
  • Search for PIC16F877A & LEDs 
  • Click on Virtual Instruments Mode then choose VIRTUAL TERMINAL & OSCILLOSCOPE
  • Click on Terminal Mode then choose (DEFAULT & POWER &GROUND)
  • finally make the circuit below and start the simulation
Proteus circuit diagram for PIC16F877 interrupt implementation

That’s all!

If you have any questions or suggestions don’t hesitate to leave a comment below

You Might Also Like

Leave a Comment


Are you sure want to unlock this post?
Unlock left : 0
Are you sure want to cancel subscription?
-
00:00
00:00
Update Required Flash plugin
-
00:00
00:00