PIC Timer Interrupts

Friday, October 14th, 2005

Here’s a very basic program to use TMR0 and an interrupt for TMR0 to do something every second.
I’m using a 4Mhz clock.

We are setting up the PIC so that everytime TMR0 reaches it’s max value(this is configurable), a Timer Interrupt occurs.


'Works w/ 18Fxx2 - James Tu 06/01/2004

'This program sets up a TMR0 interrupt
'The interrupt happens every 1 sec!
'I timed it...it's pretty precise

'It changes the state of an LED every second.

led var PORTB.4
ledstate VAR BIT

ledstate = 1

INTCON2.7 = 0 'Enable PORTB pullups...18Fxx2

'setup TIMER0
'set the high and low bytes of TMR0...
'we'll be using it in 16-bit mode
'This is equal to 65535 - 62500 = 3035...
'Calculated to give us 1 sec interrupts with 1:16 prescalar
TMR0H = $0B

'Enables TMR0, set to 16-bit
'Enable Pre-scalar
'Set prescalar value 1:16
T0CON = %10000011

On Interrupt Goto myint ' Define interrupt handler
'Enable Timer0 Interrupt
'Turn on INTCON.7(GIE) and INTCON.5 (TMR0IE)
INTCON = %10100000

TRISB.4 = 0


led = ledstate

Goto loop ' Do it forever

' Interrupt Service Routine
Disable ' No interrupts past this point
if ledstate == 1 THEN
ledstate = 0
ledstate = 1
INTCON.2 = 0 ' Clear TMR0 interrupt flag
TMR0H = $0B ' put 3035 in TMR0 for 1 sec interrupts
Resume ' Return to main program


Instead of changing the state of the LED, you can increment a variable…If have you have a variable called
SECONDS, you can add 1 to SECONDS when this timer interrupt occurs. This will allow you to keep time…for time event driven processing.

TMR0 can hold a 16-bit value or an 8-bit value
TMR0 has a pre-scalar that can be set to either 2,4,8,16,32,64,128, or 256.
(What the pre-scalar do is that it slows down the counting of TMR0. If the pre-scalar is set to 32, TMR0 increments by 1 every 32 PIC clock “ticks”)

Here’s the math…

  • 4Mhz crystal means an internal clock of 1Mhz
  • 1Mhz means there’s an internal clock “tick” every .000001 sec.
  • TMR0 can hold either a 16-bit(65536) or an 8-bit(256) value…I chose 16 (therefore TMR0 can count from 0 to 65535)
  • If we just left it like this, TMR0 counts from 0 to 65535 and the TMR0 Interrupt will happen every 0.065536 sec (65536 * 0.000001) .
  • We want TMR0 to interrupt every 1 sec.
  • If we set the pre-scalar to 16, TMR0 will interrupt every…0.065536 * 16 = 1.048576 sec…pretty close to 1 sec.
    • If you want you can leave it at this. If you want really precise timing, you have to do the following…you have to fill TMR0 with a starting value.(TMR0 is just a register so you can set it to any value.)
    • We want the solution to the equation:
      • value * 0.000001 * pre-scalar = 1.0 sec
      • value = 1.0/(0.000001 * 16) = 62500
    • So we want TMR0 to count 62500 not 65536. What we can do is to set TMR0 to 65535-62500 = 3035. So it actually counts from 3035 to 65535 which is 62500! We do this at the beginning of the program and every time an interrupt happens.
    • TMR0 is a 16-bit register in my example, so we have to write two bytes…one is written to TMR0H (high byte) and TMR0L (low byte).

That’s it!

The table below shows the interrupt intervals you can expect from a 4Mhz clock, and a 16-bit TMR0.

prescalar 2 4 8 16 32 64 128 256
TMR0 INT happens every (sec) 0.131 0.262 0.524 1.05 2.09 4.19 8.38 16.77

“Open-collector”, “Open-drain” demystified

Friday, October 14th, 2005

You’ll come across the terms “open-collector” and “open-drain.” These are used sometimes to describe how a particular IC’s pins are implemented internally.

This and also this are good explanations of what those terms actually mean and why an IC’s pin would be designed as open-collector or open-drain.

PIC IR remote

Friday, October 14th, 2005

Here’s the info on how to control a SONY TV. (caveat you may need to do some debugging.)

You need a 555 timer to generate the 40 Khz for you.
Your pic just turns on or off the 555 to transmit the appropriate data.

Circuit link.

SIRC codes explained.

SIRC code data format

My PICBasicPro code to implement this protocol.


Found a simpler solution. Use this IC from rentron. It will generate either a 40 or 38KHz carrier frequency for you. Use the PIC program above and connect the PIC pin to DATA IN of this IC. You need a 4Mhz clock, some pullup/down resistors, and the circuit to drive your IR LED…that’s it!