Author Topic: PIC16F877A Timer0 calculation  (Read 1890 times)

0 Members and 1 Guest are viewing this topic.

Offline djsbTopic starter

  • Super Contributor
  • ***
  • Posts: 1125
  • Country: gb
PIC16F877A Timer0 calculation
« on: August 06, 2021, 04:01:57 pm »
I have this code on a PIC16F877A

Code: [Select]
/*
 * File: Main.c
 * Author: David J S Briscoe
 * PIC: 16F877A w/Ext OSC @ 8MHz, 5v
 * Program: 06_Timer_Delay
 * Compiler: XC8 (v2.31, MPLAX X v5.45)
 * Program Version: 1.0
 *               
 *               
 * Program Description: This Program uses Timer 0 for the delay between an LED
 * turning on and off.
 *               
 *                     
 * Hardware Description: An LED is connected via a 220R resistor to pin RD1 and
 *                       a switch is connected to pin RB0 with a 10k pullup resistor.
 *                     
 * Created Aug 6th, 2021
 * NOTE: To open the header file for this PIC hold down CTRL and left click on
 * a statement E.G CTRL + LEFT click on TRISDbits.TRISD1 = 0; will open the 16f877a.h header file.
 */


/*******************************************************************************
 *Includes and defines
 ******************************************************************************/

#define _XTAL_FREQ 8000000
#define BUTTON  PORTBbits.RB0       // pushbutton
#include "16F877A_Internal.h"


/*******************************************************************************
 * Function: void initMain()
 *
 * Returns: Nothing
 *
 * Description: Contains initializations for main
 *
 * Usage: initMain()
 ******************************************************************************/

void initMain(){
   
   
    ///////////////////////
    /// Configure Ports
    //////////////////////
   
    // Set PIN D1 as output
    TRISDbits.TRISD1 = 0;
    // Set PIN B0 as input
    TRISBbits.TRISB0 = 1;
   
    //Flash LED to show alive.
    RD1 = 1;
    __delay_ms(1000);
    RD1 = 0;
   
    ///////////////////////
    /// Configure Timer0
    //////////////////////
   
    // Select counter mode
    //OPTION_REGbits.T0CS = 1;
    // Select timer mode
    OPTION_REGbits.T0CS = 0;
   
    // Assign Prescaler to TIMER0
    OPTION_REGbits.PSA = 1;
    OPTION_REGbits.PS = 0b111;      // prescale = 256
                                    // -> increment TMR0 every ? us
                                    // Change as needed.


   
    // Zero Timer
    TMR0 = 0;
    // Enable timer0 interrupts and clear interrupt flag
    INTCONbits.TMR0IE = 1;
    INTCONbits.TMR0IF = 0;
}

/**************************************************************************/




/*******************************************************************************
 * Function: Main
 *
 * Returns: Nothing
 *
 * Description: Program entry point
 ******************************************************************************/

void main(void) {
    initMain();
   
    // define and initialize variables
    // Flashing @ 7.6345 KHz
    // On for 123.5uS off for     
    // 7.5us. Duty cycle 94.277% ON   
    //  5.723% OFF, PERIOD 130.98uS
   
    for(;;)
        // Delay 500 ms? for 500KHz clock yes. NOT for an 8MHz clock that i'm using.
    {
        TMR0 = 0;
        while( TMR0 < (int)(500/2.048))
        {
            RD1 = 1;
        }
       
        // Turn off LED
       
        RD1 = 0;
    }
   

   


}

These are the measurements on my scope (as described in the code comments above).

LED Flashing @ 7.6345 KHz
On for 123.5uS
Off for 7.5us.
Duty cycle 94.277% ON                      
5.723% OFF,
PERIOD 130.98uS

The clock frequency is 8MHz.

i'm trying to understand how these values are arrived at. I've had a look for an explanation that I can understand, but every one I've tried has left me more confused. Can someone help me figure this out? Thanks.
David
Hertfordshire, UK
Retired University Electronics Technician, London, PIC16/18, CCS PCM C, Arduino UNO, NANO,ESP32, KiCad V10+, Altium Designer 21.4.1, Alibre Design Expert 28 & FreeCAD beginner. LPKF S103,S62 Operator, Electronics instructor. Credited KiCad French to English translator.
 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 4845
  • Country: us
Re: PIC16F877A Timer0 calculation
« Reply #1 on: August 06, 2021, 05:10:54 pm »
The instruction clock is Fosc/4 = 500 ns (0.5 us).   Your on and off times per calculation fit that limit for resolution.

The sum of on and off = 131 us = 7.633.6 kHz (calculated).

Your measurements are off a little.  Sources of error are your scope and oscillator frequency.  Neither is exact.
 

Offline djsbTopic starter

  • Super Contributor
  • ***
  • Posts: 1125
  • Country: gb
Re: PIC16F877A Timer0 calculation
« Reply #2 on: August 06, 2021, 06:18:24 pm »
So it's 0.5uS x 244 (0.000122s)? How is the off time calculated? Thanks.
David
Hertfordshire, UK
Retired University Electronics Technician, London, PIC16/18, CCS PCM C, Arduino UNO, NANO,ESP32, KiCad V10+, Altium Designer 21.4.1, Alibre Design Expert 28 & FreeCAD beginner. LPKF S103,S62 Operator, Electronics instructor. Credited KiCad French to English translator.
 

Offline jpanhalt

  • Super Contributor
  • ***
  • Posts: 4845
  • Country: us
Re: PIC16F877A Timer0 calculation
« Reply #3 on: August 06, 2021, 06:43:47 pm »
With all mid-range PICs, it take 4 system clock oscillations for an instruction cycle.  Thus, the time for an instruction cycle is 4 x 1/Fosc. Then, 1/(8x10^6) = 125 ns, and 4x125 ns = 0.5 us.

Timer0 counts on every instruction cycle and rolls over to zero after 255 (i.e., 8-bit).  If you want an interrupt for less than 256 x 0.5 us, just pre-load a number in the timer.

Aside from that, its just multiplication, addition/subtraction , and sometimes counting (e.g., if you want 1 interrupt for every 5 rollovers).
« Last Edit: August 06, 2021, 06:45:27 pm by jpanhalt »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

- - -
-->