Proton Tutorial - TMR0

TMR

TMR0 is an 8 byte timer that can be pre-scaled to change vary its incrementing cycle. Pre-scaling is important as we may want the Timer Register to increment faster/slower in different applications. The speed in which it does cycle is dependent on both the external crystal speed and the pre-scaling options.

To change the pre-scaling for TMR0, the following bits of the OPTION Register are modified:

TMR0 Pre-Scale Options
OPTION_REG.0 = X '000 - 1 : 2
 OPTION_REG.1 = X '001 - 1 : 4
 OPTION_REG.2 = X '010 - 1 : 8
  '011 - 1 : 16
  '100 - 1 : 32
  '101 - 1 : 64
  '110 - 1 : 128
  '111 - 1 : 256
 

 

The OPTION register contains 8 bytes of information, the other 5 are for completely different options, so when I modify settings that are shared in Byte registers with other options, I access them like above, so I don't accidentally change anything I don't want to.

To change the pre-scaler too 1:4 (increment the TMR0 register every 4th clock cycle), the following would be used:

1:4 Pre-Scale
OPTION_REG.0 = 1
OPTION_REG.1 = 0
OPTION_REG.2 = 0

 

Now to make a timer that can be used to count mS and Seconds very accurately. An easy way to find out how much time each clock cycle will take is to use a cycle calculator such as this. Make sure that the Internal Check Box is selected, now be sure that 4Mhz is the clock speed, and the pre-scaler is set to 1:2, you will see that the TMR0 period is now 512uS, so every time the TMR0 clock reaches 255, and rolls over to 0, 512uS has elapsed. Now we have a basis in which we can write our program.

Proton PDS TMR0 Example
Device = 16F877
Xtal = 4
 
Dim uS as Word
Dim mS as Word
Dim S as Word 
 
Symbol GIE = INTCON.7 ' Global Interrupt Enable Bit
 Symbol TMR0_uS = 512 ' Set time interval of TMR0
 Symbol TMR0_Enable = INTCON.5 ' This option enables TMR0 interrupts
 Symbol TMR0_Overflow = INTCON.2 ' This is the TMR0 overflow flag
  
ON_INTERRUPT Int_Sub
 
Goto Initialization 
 
Int_Sub:
 
 GIE = 0
 
 If TMR0_Overflow = 1 And TMR0_Enable = 1 Then
 TMR0_Overflow = 0
 uS = uS + TMR0_uS
 If uS >= 1000 Then
 uS = uS - 1000
 mS = mS + 1
 If mS >= 1000 Then 
 mS = mS - 1000
 S = S + 1
 EndIf
 EndIf
 EndIf
 
 GIE = 1
 
 Context Restore
 
Initialization:
 
 TMR0_Enable = 0 ' Disable TMR0 interrupts
  
 uS = 0 ' Clear timer registers
  mS = 0 ' 
  S = 0 '
  
 OPTION_REG.0 = 0 '000 - 1 : 2
 OPTION_REG.1 = 0 '
 OPTION_REG.2 = 0 
 OPTION_REG.5 = 0 ' Select Internal Clock Source
 
 TMR0 = 0 ' Clear the TMR0 register
 
 TMR0_Enable = 1 ' Enable TMR0 Interrupts
 
 GIE = 1 ' Enable Global Interrupts
 
Main:
 
 Repeat ' Create a loop
 
 Until S = 60 ' That waits for 60 seconds
 
 ' 60 seconds has occurred
 
 S = 0 ' Clear the seconds register
 
 Goto Main ' Loop for ever

 

Forum Activity

Member Access