QUOTE (soft2 @ Dec 17 2007, 07:40 PM)

There are several threads discussing timer issues, implementing free running timers, etc. I use different methods depending on the app... and hoping some of you can help me find the best method for my current project.
Using a PIC18xxxx at 20 Mhz, Timer 1 prescaled 1:4 provides adequate resolution (approx 1 uS). The timer is used by several things at once, some of them measuring intervals of several minutes, so I can't reset it. My question is what is the most efficient method of storing and retrieving the accumulated time? Note that it is not required to be in sync with real time. I created a global variable that is incremented each time Timer 1 overflows on interrupt. I would like to have a handy object that I can use most anywhere to give me the current accum time count. There are a few ways i can do this:
CODE
// global counter incremented each time tmr1 overflows
volatile unsigned int uTimer = 0;
// here is a handy variable we can use every time we need to access the accumulated time
#define TIMER (uTimer*65536 + tmr1l + tmr1h*256)
void interrupt( void )
{
//Handle timer1 interrupt
if( pir1 & (1<<TMR1IF) )
{
uTimer++; // increment ulTimer
clear_bit( pir1, TMR1IF ); //clear timer1 interrupt bit
}
}
There are at least 2 problems with defining TIMER this way. First it's not efficient - multiplying 16 and 32 bit numbers is slow and hogs code space. Tried shifting bits but the way the compiler implements << it was actually slower than multiplying! Probably the algorithm I used

. I have to use TIMER many times in the code. The other problem is that every once in 65000 cycles the interrupt will fire before it finishes calculating TIMER, producing an inacurate result.
I tested several variations of functions for TIMER() that returned unsigned long. None of them effectively solve the problem that on rare occasion the interrupt can roll over before completing the result, but some were a lot faster and smaller. I cobled one solution together that borrowed code from MAKESHORT( dst, lobyte, hibyte ) that worked the best but I don't know asm (although lots of experience with c/c++). I would prefer something that didn't require a function with the resulting overhead.
How do you solve this problem? OK I can go with an Arm7 solution w/ 32 bit processing at 40 Mhz. But this app runs on small batteries and for other reasons I want to use a PIC.
Thanks
Use a union. It's what unions are for:
CODE
typedef struct _access {
unsigned char lowByte;
unsigned char midByte;
unsigned int highWord;
} access;
typedef union _timerUnion {
unsigned long longVal;
access bytes;
} timerUnion;
timerUnion theTimer;
#define TIMER (theTimer.bytes.lowByte = tmr1l, theTimer.bytes.midByte = tmr1h, theTimer.longVal)
#define uTimer theTimer.bytes.highWord
Yes, it's kind of messy with the typedefs, but on the PIC16 version of the compiler at least, the syntax works. I didn't succeed with the PIC16 compiler putting a structure definition inside a union. YMMV with the PIC18.
The TIMER definition uses on the comma operator and has the value of the last expression, ie. theTimer.longVal. It would be more readable if it was split into two defines:
#define READTIMER theTimer.bytes.lowByte = tmr1l; theTimer.bytes.midByte = tmr1h;
#define TIMER theTimer.longVal
Then you could do the following:
READTIMER;
/* expression involving TIMER */
I used unions and defines in a similar way to pick apart packet headers in a protocol for the nRF2401 wireless chip. It works fine, has no overhead over accessing any other global variable, and realisticly, should produce the same code as doing it by hand in assembly.
Orin.
This post has been edited by Orin: Dec 19 2007, 08:07 AM