Embedded Software Development: PIC18F4520 Timer Programming
Timers are the most essential peripheral for a microcontroller and every controller provides a provision for using them. They are mostly used for exact delay generation. Timers are also used in various other operations like PWM signal generation, auto-triggering of several other peripherals etc.
To put it simply, timers may be thought of as a register whose value keeps increasing or decreasing by a constant rate without the help of the CPU. The CPU can read or write this register any time to find out how much time has elapsed. The Timer register can have the following bit length:
8 bit timers – These can count between between 0-255
16 bit timers – These can count between 0-65536
32 bit timers – These can count between 0-4294967296
A timer has a clock source, for example if the clock source of 10KHz is input to a timer then one increment will take 100uS. This clock source can be obtained from the CPU clock. PIC also has a prescaler, to divide the CPU clock to obtain a smaller frequency. The PIC Micro that we will use in this example has prescaler division factors of 256, 128, 64, 32, 16, 8, 4, 2 and 1.
When a timer register has already counted the maximum value it can count, an overflow occurs and the register is reset. At overflow the counter value become 0 again. For example when an 8-bit timer has the value 255 and receives another clock, it will be set to 0 and generate an overflow. An overflow can trigger an interrupt, which can be handled by the ISR.
Even with all the knowledge above, setting up a PIC timer to the correct frequency can be tricky for beginners. In the following section we will configure and setup one of the four timers of PIC18F4520. We will configure TIMER0 in 8-bit mode, to use clock source from prescaler and the overflow interrupt enabled. Before we get to the actual codes, there are a few calculations to be performed.
Prescaler = FCPU/256 (Note: FCPU = FOSC/4)
In our case, we are using a 20 Mhz XTAL Crystal. Therefore,
FOSC = 20Mhz and FCPU = 20Mhz/4 = 5 Mhz
Time Period = 0.2uS
Prescaler Period = 0.2 x 256 = 51.2 uS
Overflow Period = 51.2 x 256 = 13107.2 uS (because each overflow takes 256 counts in 8 bit mode)
Therefore, number of overflows in 1 second would be 1/0.0131072 = 76.2939
The above means that, after the timer is switched on, we will have to count for 76 overflows (in our ISR) to know that 1 second has expired. We can use a counter variable to keep track of overflows and additional logic as required to handle the other events based on the time expired. Below is a very basic snippet of code that can be used to setup the timer.
unsigned char counter=0;//Overflow counter
//Prescaler is divide by 256
//Timer Clock Source is from Prescaler
T0CS=0; //Prescaler gets clock from FCPU (5MHz) T08BIT=1; //8 BIT MODE
TMR0IE=1; //Enable TIMER0 Interrupt
PEIE=1; //Enable Peripheral Interrupt
GIE=1; //Enable INTs globally
TMR0ON=1; //Now start the timer!
while(1); //Sit Idle Timer will do every thing!
//Main Interrupt Service Routine (ISR)
void interrupt ISR()
//Check if it is TMR0 Overflow ISR
if(TMR0IE && TMR0IF)
//TMR0 Overflow ISR
counter++; //Increment Over Flow Counter
//Your Logic After every second goes here
counter=0; //Reset Counter