Select Page

The PIC10F322 has two Timer Modules – we are going to take a look at TMR0 (Timer 0).

Timer 0 – is an 8bit timer/counter – that can be incremented by either an external signal or internal instruction clock FOSC/4. When the timer overflows – (reaches 0xFF and turns over to 0x00) it sets an interrupt flag that can be read and/or can be setup to trigger an interrupt if desired.

In counter mode – the Timer0 module will increment on every rising or falling edge of the T0CKI pin.
8-Bit Counter mode using the T0CKI pin is selected by setting the T0CS bit in the OPTION_REG register to ‘1’.

In timer mode – The Timer0 module will increment every instruction cycle, if used without a prescaler. 8-Bit Timer mode is selected by clearing the T0CS bit of the OPTION_REG register.

Timer Prescaler

A single software programmable prescaler is available for use with Timer0. The prescaler assignment is
controlled by the PSA bit of the OPTION_REG register. To assign the prescaler to Timer0, the PSA bit must be cleared to a ‘0’. There are 8 prescaler options for the Timer0 module ranging from 1:2 to 1:256. The prescale values are selectable via the PS<2:0> bits of the OPTION_REG register.

What is a prescaler, think of it like this. The default is 1 to 1. For every pulse the timer increases by 1. If we put in an 1:4 prescaler value – it will take 4 pulses to increase the timer by 1. In short think of it like a divider.

The example that you will find below – is a replacement for the LED Blinker. In the previous examples – we used the __delay_ms macro – which basically inorder to generate the delay, required executing NOPs (No Operation) commands on the MCU. This can consume a lot of program memory space and leaves the CPU spinning its wheels.

Enter Timer 0 – It is what it is – a hardware counter. It also has a prescaler that can be enabled to give longer overflow times.

Code Overview

Here is what the code does..

First we set the PIC10F322 to run at 31Khz.

Enable TMR0 – to use a prescaler of 16

Enable an output on PORT.A0 – this is where the LED is.

Next we check the overflow flag to see if TMR0 did overflow – if so, we toggle the LED on or off – and reset the overflow flag.

*Resetting the overflow flag is important, as it can only be done in software. Let me say it again.. It is important to reset the overflow flag, it does not do it itself.

A break down of the math we are using…

With a 31Khz clock we get.. FOSC/4 a 7.75Khz instruction clock.
At 7.75Khz, TMR0 increments every 129us. Without a prescaler 1/7750
Adding in a prescaler of 16.
Now TMR0 increments every 2ms 129 x 16
TMR0 overflows every 255 cycles, we get 510ms per overflow.

See the logic output below – it is around 511ms, however we need to figure in the code to check the overflow flag, reset the flag, and the code that toggles the output. However, it is close enough for what we are doing.

Which reminds me of a joke… a scientist and engineer see a person they are attracted to at the end of a hallway. The scientist takes half-steps and after a few steps, says.. I can never be close enough. The engineer on the other hand, sees the same problem and says… I can get close enough for all practical purposes.

Logic Scope View



10F322 blink led circuit

The Code

 * File:  timer0_example.c
 * Author: Jamie Starling - 
 * Created on:  September 7, 2021, 7:45 PM
 * Code/Circuit provided as-is.

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

//Device Configuration
#pragma config FOSC = INTOSC  // Oscillator Selection 
#pragma config BOREN = ON    // Brown-out Reset
#pragma config WDTE = OFF    // Watchdog Timer
#pragma config PWRTE = ON    // Power-up Timer
#pragma config MCLRE = OFF   // MCLR Pin Function Select bit->MCLR pin function is digital input, MCLR internally tied to VDD
#pragma config CP = OFF      // Code Protection 
#pragma config LVP = OFF     // Low-Voltage Programming 
#pragma config LPBOR = ON    // Brown-out Reset Selection bits
#pragma config BORV = LO    // Brown-out Reset Voltage Selection
#pragma config WRT = OFF    // Flash Memory Self-Write Protection

//Used to calculate the delay time - Change depending on processor Speed
#define _XTAL_FREQ 31000  //31Khz

void setup(void);

void main(void)
          if (INTCONbits.TMR0IF == 1)  //Check to see if the overflow TMR0 flag is set
              INTCONbits.TMR0IF = 0; //Clear the TMR0 interrupt flag
              LATA ^= 0b00000001;  //Use XOR and mask to flip the bits what is on becomes off.                 

void setup(void)
    //Set the System Clock - You can change this to match the setting you are looking for
    OSCCONbits.IRCF = 0b000;  //Set System Clock to 31Khz
    TMR0 = 0;  //Set TMR0 to 0
    INTCONbits.TMR0IF = 0; //Clear the TMR0 interrupt flag
    OPTION_REGbits.PS = 0b011;  //Set TMR0 Prescale to 16
    OPTION_REGbits.PSA = 0; //Assign Prescaler to TMR0 
    OPTION_REGbits.T0CS = 0; //Set TMR0 Clock source to FOSC
    /*With a 31Khz clock we get.. OSC/4 7.75Khz instruction clock.
    * TMR0 increments every 129us. Without a prescaler 1/7750
     * Adding in a prescaler of 16. 
     * TMR0 increments every 2ms  129 x 16
     * TMR0 overflows every 255 cycles, we get 510ms per overflow.    
    ANSELAbits.ANSA0 = 0;
    TRISAbits.TRISA0 = 0;
    LATAbits.LATA0 = 0;

Have a Project or Idea!?

I am Available for Freelance Projects

My skills are always primed and ready for new opportunities to be put to work, and I am ever on the lookout to connect with individuals who share a similar mindset.

If you’re intrigued and wish to collaborate, connect, or simply indulge in a stimulating conversation, don’t hesitate! Drop me an email and let’s begin our journey. I eagerly anticipate our interaction!

Pin It on Pinterest

Share This