volatile unsigned int tmsClock = 0;
void Initialize_Timer_1(void)
{
TMR1L = 0x00;
TMR1H = 0x00;
T1CONbits.T1CKPS0 = 0; // 1:1 prescaler 10Mhz
T1CONbits.T1CKPS1 = 0;
T1CONbits.T1OSCEN = 0; // oscillator disabled
T1CONbits.TMR1CS = 0; // use the internal clock
T1CONbits.RD16 = 1; // timer 1 register operations are done in one 16-bit access
PIE1bits.TMR1IE = 1; // Enable interrupt on overflow
IPR1bits.TMR1IP = 0; // overflow interrupt is low priority
T1CONbits.TMR1ON = 1; // Timer 1 is enablED
}
void Timer_1_Int_Handler(void)
{
// this function will be called when a timer 1 interrupt occurs
tmsClock++;
}
The handler simply increments a 16-bit counter, every 0.00655 seconds, which rolls over every 429.49 seconds. Then, I wrote these functions to fetch the 32bit snapshot of the timer:
unsigned int GetTick(void) //Gets 16-bit timer value
{
unsigned char Temp_Buf; // 8-bit temporary buffer
unsigned int Timer_Snapshot; // 16-bit variable
Temp_Buf = TMR1L; // TMR1L must be read before TMR1H
Timer_Snapshot = TMR1H;
Timer_Snapshot <<= 8; // move TMR1H data to the upper half of the variable
Timer_Snapshot += Temp_Buf; // we now have all sixteen bits
return Timer_Snapshot;
}
unsigned long GetTime(void) //Gets 32-bit timer value
{
unsigned long ThisTick;
ThisTick=tmsClock;
ThisTick <<= 16; //Mutliply by 65536
ThisTick += GetTick(); //Add timer snapshot
return ThisTick;
}
Now GetTime() works as intended, except every second or two I get a strange (really large) value returned. Any ideas?
BTW: I discovered this error around 3:00am on ship day, which was wreaking havoc on our autonomuous code. Without a controller to test on, I haven’t been able to trace the problem.
I agree with Jamie, this printf will return bogus results. It only processes 16 bits and treats them as a signed int.
[edit]My error. I forgot about the %lx format being available in printf. Our original issue with printing longs was with interpreting signed longs easily. Thanks for the correction Random.
Though, as to the orignial question, I think it may be a critical section problem, where the interrupt code is running during a critical part of the main code. Specifically:
ThisTick=tmsClock;
That line actually compiles to about 10 lines of assembly. If the interrupt occurs during that section, really odd things can happen. You may need to disable interrupts right before that, and reenable them right after it.
[edit] Further thought on this (and clarification as to the actual problem) makes me realize that this wouldn’t occur quite that often./edit
Notice the extra 0’s. The problem is the printf function doesn’t zero pad the output like it should. That is ‘ok’ for the ints, but for the longs it causes problems (In the printf lib, the printi function actually gets called twice for longs. once for each word.)