//#define TESTING_TIMER /* This module contains a software PIC timer based on Timer0 overflows. It requires the following: (1) Global interrupts enabled (2) Timer0 not used for anything else (3) Running off a 20MHz oscillator (3) Copy pasting the following into the interrupt response routine in the main C file: if (TMR0IE && TMR0IF) TimerPIC_ISR(); (4) Including TimerPIC.h Originally, this module updated all the timer flags inside the interrupt response. However, this took over 100 us and caused problems with other precise timing interrupts (OC). Instead the timers have been rewritten to update outside of an interrupt. To use a timer: (1) Initialize the module using TimerPIC_Init (2) Start a timer using TimerPIC_InitTimer(Num,NewTime), where Num is 0-7 and NewTime is in ms (3) Check if the timer has expired using if(TimerPIC_IsTimerExpired(Num) == TimerPIC_EXPIRED) */ //#include "pic16f777.h" #include <stdio.h> #define _LEGACY_HEADERS #include <htc.h> #include "BITDEFS.h" #include "TimerPIC.h" #ifdef TESTING_TIMER //__CONFIG(UNPROTECT & WDTDIS & PWRTDIS & HS); __CONFIG (UNPROTECT & WDTDIS & PWRTDIS & HS); #endif TESTING_TIMER typedef unsigned char Tflag_t; typedef struct timer_struc{ unsigned int TimerTime; unsigned int LastTime; }Timer_t; /*---------------------------- Module Functions ---------------------------*/ /*---------------------------- Module Variables ---------------------------*/ static Timer_t TMR_TimerArray[sizeof(Tflag_t)*8]; // Store times for all timers static unsigned int time; /* this is used by the default RTI routine */ void TimerPIC_Init(void) { // Set up overflows every 0.2048 ms: 2^8*((20MHz/4)/4) T0CS = 0; // Internal instruction clock (fosc/4) PSA = 0; // Assign prescaler to Timer0 PS2 = 0; PS1 = 0; PS0 = 1; // Prescaler = 1:4; TMR0IF = 0; // Clear flag TMR0IE = 1; // Turn on interrupt } TimerPICReturn_t TimerPIC_InitTimer(unsigned char Num, unsigned int NewTime) { // Schedule when timer expires TMR_TimerArray[Num].TimerTime = NewTime; TMR_TimerArray[Num].LastTime = TimerPIC_GetTime(); return TimerPIC_OK; } TimerPICReturn_t TimerPIC_IsTimerExpired(unsigned char Num) { if( (TimerPIC_GetTime() - TMR_TimerArray[Num].LastTime) > TMR_TimerArray[Num].TimerTime) { return TimerPIC_EXPIRED; } else return TimerPIC_NOT_EXPIRED; } unsigned int TimerPIC_GetTime(void) { return (time); } void TimerPIC_ISR(void) { static unsigned char counter = 0; // Clear the source of the interrupt TMR0IF = 0; // We're interrupted every 0.2048ms, so only update every 5th time if (++counter == 5) { // keep the GetTime() timer running time++; counter = 0; } } #ifdef TESTING_TIMER void interrupt TimerExpired(void) { if (TMR0IE && TMR0IF) TimerPIC_ISR(); } void main(void) { // Turn off analog inputs PCFG0 = 1; PCFG1 = 1; PCFG2 = 1; PCFG3 = 1; TimerPIC_Init(); TimerPIC_InitTimer(0,100); TRISB3 = 0; TRISB4 = 0; RB4 = 1; RB5 = 1; GIE = 1; while(1) { if(TimerPIC_IsTimerExpired(0) == TimerPIC_EXPIRED){ TimerPIC_InitTimer(0,100); RB4 ^= 1; } } } #endif