Select Page

In the previous post I wrote about using the PIC10F322 Interrupt. In this post is the the complete code that will use timer0, to replace the __delay_ms() macro.

Why would we want to replace the __delay_ms() macro?


The macro has some limitations, great if you want to bang something out. However, the macro uses a series of NOP instructions to work. Which can take up a lot of code space, depending on what you are doing.

By using timer0 and interrupts we get around this problem and create a timer than can accept a variable – for example – if we wanted to read an analog value and update the timer – based on the analog input. The macro will not work, but this will…

And incase you are wondering… yes the next post will be on using the analog input functions of the PIC10F322..

The code will blink an LED on Port.A0.

The Circuit

10F322 blink led circuit

The Code

/*
 * File:   isr_timer.c
 * Author: Jamie
 *
 * Created on 9/13/2021, 8:56 PM
 */



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

#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 8000000  //8 MHz (default after Reset)


//Function prototypes
void setup (void);
unsigned long millis(void);
void delay(uint32_t ms);


//Variables
volatile unsigned long timer0_millis = 0;


//interrupt handler 
void __interrupt () isr_routine (void) {

//TMR0 = 8;
timer0_millis +=1;  //increase the counter by 1  
INTCONbits.TMR0IF = 0; //clear tmr0 irq flag
}

void main(void)
{
    setup();
    
    while(1)
    {
       LATAbits.LATA0 = 1; //turn on port A.0
       delay(500);
       LATAbits.LATA0 = 0; //turn off port A.0
       delay(500);
    }
    
}

void setup (void)
{
    //Set Port A0 as output
    TRISAbits.TRISA0 = 0;
    
    //Clear any analog and port settings
    ANSELA = 0x00;
    LATA = 0x00;
    
    /*Set TMR0 to use FOSC/4 At 8Mhz the timer with increment at 2Mhz
    That is 500us       
    TMR0 will overflow ever 128us. Which is faster than we want - I am aiming for 1ms.
    So lets use a prescaler to get it close
    Assign prescaler to TMR0 With prescaler of 8 we get  500ns * 256 * 8 = 1.024ms
    Then set the prescaler */
    
    OPTION_REGbits.PSA = 0;
    OPTION_REGbits.PS = 0b010; //prescaler of 8
    
    //To Start the timer we need to set the clock source to fosc/4 but first clear the timer just to make sure    
    TMR0 = 0;    
    OPTION_REGbits.T0CS = 0;
    
    //Assign interrupt to timer 
    INTCONbits.TMR0IF = 0; //clear tmr0 irq flag
    INTCONbits.TMR0IE = 1; //enable tmr0 irq enable
    INTCONbits.GIE = 1; //enable global interrupts      
}


//Reads the MS variable
unsigned long millis(void)
{
	unsigned long m;
	// disable interrupts while we read timer0_millis or we might get an
	// inconsistent value (e.g. in the middle of a write to timer0_millis)
	INTCONbits.GIE = 0;
	m = timer0_millis;
    INTCONbits.GIE = 1;
	
	return m;
}



//Delay based on the number of MS
void delay(uint32_t ms)
{
    //Get the timer value as we go into the delay
	uint32_t start = millis();
    
    //We wait here until while current timer value, minus the start value, is less than the value we want
	while (millis() - start < ms){}
    
}

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!

jamie@jamiestarling.com


Pin It on Pinterest

Share This