Log in

View Full Version : Timer0 stubbornly not working


Kevin Sevcik
09-03-2006, 22:30
Hey all,

I'm embarrassed to have to ask, but we're using Timer0 in our code to give us a 60Hz cycle on a PID loop. And the darned thing refuses to work. After an hour or troubleshooting and fiddling with code and looking at a frequency counter, we were stuck at about 38.somethingHz. I finally realized that this was a full count from 0 to 65535 at a prescale of 1:4. So our pre-load values aren't pre-loading properly. Here's a code snippet of the initializing and the interrupt handler:

//Initialize
T0CON= 0b00000001; ////1:4 Prescale
TMR0H= 0X5D; //Pre-load TMR0 to overflow at 60 Hz
TMR0L= 0X3D;
T0CONbits.TMR0ON= 1; //Turn timer on

T1CON= 0b10000110; //Set Timer 3 in async counter mode, 16-bit read
TMR1H=0x00;
TMR1L=0x00;
T1CONbits.TMR1ON = 1; //Turn Timer on


//Interrupt handler
else if (INTCONbits.TMR0IF && INTCONbits.TMR0IE) // timer 1 interrupt?
{

INTCONbits.TMR0IF = 0; // clear the timer 0 interrupt flag
TMR0H = 0X5D; //Pre-load TMR0 to overflow at 60Hz
TMR0L = 0X3D;
Timer1L = TMR1L;
Timer1H = TMR1H;
TMR1H = 0x00;
TMR1L = 0x00;
fMainTimer = 1;
}

We've got a similar problem with Timer1. We're using it as an asyncronous counter in 16-bit read/write mode. Unfortunately, the high byte just isn't getting read. Timer1H is always equal to zero, even when it shouldn't be. We've tried using it not in 16-bit read/write mode, and it works fine. But then we have to worry about getting incorrect readings if the low byte overflows as we're reading.

I'll note that the commonality here is the Timer0 exclusively uses 16-bit read/write mode, and Timer1 wasn't working in 16-bit read/write mode. So. Does anyone know if there's some extra step I need to take to get things to work in 16-bit read/write mode? Is it just broken? Is there PIC errata about this too? Will I ever stop ending my sentences in question marks?

ericand
09-03-2006, 23:24
I might think you are missing the part where you enable the interrupt except
you say you are getting it but at a slower rate. Do you have any other
interrupts happening? I think your ISR will pick up the timer if the ISR gets called for something else (even if the timer has not been enabled to generate
an interrupt).

I think the bits you need to set for timer 0 are in the INTCON register.
Check the PIC data sheet for the exact bits.

This is what we do when we set up timer1. However,

IPR1bits.TMR1IP = 0;
PIE1bits.TMR1IE = 1;
INTCONbits.GIEL = 1;

We are using timer 1 to provide a clock to run a number of different functions.

We did our initial setup using the timer white paper that is published on the IFI
web site. If you follow the instructions in the paper exactly, you will get timer1
up and running.

http://www.ifirobotics.com/docs/timers_white_paper_2004-jan-14.pdf

we generalized it so we can can set an #define to the base HZ rate we want.

We also use timer 2 via Kevin's ADC code, but that worked without modification.
You may want to check that one out for a working example as well.

Matt Krass
09-03-2006, 23:45
I do believe that you have to write to the TMR0L then TMR0H, if memory serves, there's a hardware lock engaged when the low byte is accessed, doing it out of order can produce odd results. Try reversing those lines.

Kevin Sevcik
10-03-2006, 00:01
I do believe that you have to write to the TMR0L then TMR0H, if memory serves, there's a hardware lock engaged when the low byte is accessed, doing it out of order can produce odd results. Try reversing those lines.
I thought I did. The PIC datasheet specifically says that the high byte is saved in a buffer until the low byte is written, however. I suppose I can try transposing them tomorrow, but that'd be terribly confusing. Also, to the above poster, the interrupt is set up just fine and is interrupting things as it should. Timer0 just isn't working properly.

About the IFI whitepaper. I looked it over already, and they very specifically aren't enabling the 16-bit read/write mode. Which is just fine for using it as a timer like they do, but is problematic when using it as a counter.

Matt Krass
10-03-2006, 00:34
I thought I did. The PIC datasheet specifically says that the high byte is saved in a buffer until the low byte is written, however. I suppose I can try transposing them tomorrow, but that'd be terribly confusing. Also, to the above poster, the interrupt is set up just fine and is interrupting things as it should. Timer0 just isn't working properly.

About the IFI whitepaper. I looked it over already, and they very specifically aren't enabling the 16-bit read/write mode. Which is just fine for using it as a timer like they do, but is problematic when using it as a counter.
Perhaps I'm confusing the PICs and Atmel chips again, anyway though try it, because you're writing the Timer1 bytes in that order it appears and it seems to be working for you.

The Lucas
10-03-2006, 01:15
Yes, all five timers can be available for you to use in your code.

Timers 1-4 are available by default.

Timer 0, however, is used by the Generate_Pwms() function if you use ifi_library.lib or FRC_library.lib. These libraries use Timer0 to synchronize any PWM outputs generated by the User processor to make sure they avoid any SPI interrupts.

If you want to use Timer0 yourself, then you can replace ifi_library.lib/FRC_library.lib with ifi_alltimers.lib/FRC_alltimers.lib in the project.

A white paper with an example of using a timer can be found here,

You can't use Timer0 because Generate_Pwms() is screwing it up according to the FAQ here (http://www.ifirobotics.com/forum/viewtopic.php?t=62) . You are probably getting the same counts every cycle (like I was when I was trying to tach my shooter). Use a different timer. I need to sleep now, since I have robots to fix/inspect in the morning

Mark McLeod
10-03-2006, 04:29
As you can tell from Brian's post you need to delete ifi_library.lib from your MPLAB project and Add ifi_alltimers.lib in it's place.


"If you want to use Timer0 yourself, then you can replace ifi_library.lib/FRC_library.lib with ifi_alltimers.lib/FRC_alltimers.lib in the project.
"

Timer0 is getting reset by ifi_library.lib purely as a special service to the user, but you aren't using that service so you don't need that service.

The Lucas
10-03-2006, 07:08
As you can tell from Brian's post you need to delete ifi_library.lib from your MPLAB project and Add ifi_alltimers.lib in it's place.

In your competition reprogramming haste, don't forget to use an updated library (http://www.ifirobotics.com/docs/revised-frc-libraries_2-24-06.zip).
Good Luck at GLR! :)

Kevin Sevcik
10-03-2006, 22:49
Success! Thanks to all in this thread. I should've known it was something obvious I was overlooking, but I was busy squashing all sorts of other bugs, mechanical and programmatic. The alltimers library fixed Timer0 right away. The Timer1 not reading properly is still happening, but there was some code in the PIC datasheet to get a proper read without using the 16-bit read/write mode. Also, the team managed to get bitten by the dreaded 8.2V bug in our first match. The linker patch appears to be working, so we'll see if that holds up.