The Timer Modules - Timer1
Unlike the Timer0 module, Timer1 is a 16-bit length timer/counter. It can operate as a Timer, or as a synchronous/asynchronous counter. To set-up and control the Timer1 module, there is a dedicated control register named T1CON. Accessing this register will have a result on the operation of the Timer1 module.
Setting up and accessing the Timer1 module
The Timer1 module has 2 8-bit registers to represent the 16-bit length value of the module. These registers are both located in BANK0, and are named TMR1H and TMR1L. The 16-bit value comes from the pair TMR1H:TMR1L. Every increament of the Timer1 module will increase the value of TMR1L register. Every time that this register overflows, the TMR1H is increased by 1.
To set up and control the Timer1 module, you need to access the T1CON register located in BANK0. The bits of this register are explained bellow:
T1CON register BIT <6> (T1RUN):
This bit is the "Timer1 System Clock Status bit", and is available only for reading. Under certain circumstances, the PIC can change the clock input to an external 32KHz crystal connected onto the PIC. This oscillator is used to reduce the power consumption even more. This kind of configuration is most usable in RTC applications (Real Time Clock). The value that the T1RUN bit can get is:
T1CON register BITS <5:4> (T1CKPS):
These two bits are the "Timer1 Input Clock Prescaler Select bits". Unlike the Timer0 module, this one has a dedicated prescaler. The prescaler is assigned all the time to Timer1 module and always divides the incoming counts. It can be deactivited simply by choosing a 1:1 division. The values that these two bits can get are:
T1CON register BITS <3> (T1OSCEN):
This bit is named "Timer1 Oscillator Enable Control bit". The PIC has a built-in inverter connected on pins T1OSO and T1OSI. This inverter is used to generate the clock pulses from the external 32 KHz crystal. This bit will turn on and off this inverter to reduce the power consumption when not in use:
T1CON register BITS <2> (T1SYNC):
This bit is named "Timer1 External Clock Input Synchronization Control bit". When the Timer1 module operates as a counter and the counts are delivered from the T1CKI pin, the input pulses can be synchronized with the internal clock phase. This bit controls the synchronization module, and it is ignored if the bit TMR1CS is cleared:
Some considerations needs to be taken into account when choosing the synchronizing mode. First of all, for the external pulses to be synchronizes, you need to make sure that the period of each external pulse (in case that the prescaler rate is 1:1) is equal or bigger than two periods of the internal clock. Due to the fact that the synchronization module is located after the prescaler module, this means that if the prescaler rate is not 1:1, then the minimum period of the external pulses that can be synchronized is further reduced. The reduction multiplier is the same as the rate of the prescaler. If for example the prescaler rate is 1:4, then the minimum period of the external pulses to be synchronized is:
2 x Internal_Clock_Period x Prescaler_Rate = 2 x Internal_Clock_Period x (1/4) = Internal_Clock_Period / 2
Also, you should be aware that if the PIC is in Sleep mode, the synchronization module is turned off to preserve power. Thus, although the prescaler will change value in every count, the Timer1 module will NOT increase it's registers!
T1CON register BITS <1> (TMR1CS):
This is the "Timer1 Clock Source Select bit". By changing the value of this bit, you change the clock source of the module:
T1CON register BITS <0> (TMR1ON):
This is the "Timer1 On bit". This bit will control the operation of the Timer1 module:
The Timer1 Interrupt
The Timer1 module has a 16-bit register for the counts, the TMR1H:TMR1L registers, both located in BANK0. This means that it can count up to 65535. If the TMR1H:TMR1L value is 65535 (0xFFFF) and it is increased once more, both registers will become 0 (0x0000) and the TMR1 interrupt shall be raised. The TMR1IE interrupt can be controlled by the PIE1 register bit 0 (TMR1IE: TMR1 Overflow Interrupt Enable bit). When the TMR1 Interrupt is raised, the PIR1 bit 0 (TMR1IF: TMR1 Overflow Interrupt Flag bit) is raised to indicate that the TMR1 interrupt is occurred. The TMR1IF must be cleared in software (BCF PIR1,TMR1IF) for the TMR1 interrupt to be re-enabled. More info about the PIC Interrupts can be found in this link.
Reading and Writing the registers of Timer1, when operating as asynchronous counter
You should take extra care when reading or writing the two register of the Timer1 module in asynchronous mode. What could happen is that when the first register is read into W and the user is ready to read the second register, an overflow may occur from TMR1L to TMR1H. Suppese for example the value of TMR1H is '00000000' and the value of TMR1L is '11111111'. You read the TMR1H register ('00000000') and then you are ready to read the TMR1L register, but before you do, a count increases the TMR1L register and it overflows. The TMR1H becomes '00000001' and the TMR1L becomes '00000000'. Then you read the TMR1L. The value that you get from the pair is 00000000:00000000, but you should have got 00000001:00000000 instead. The same would happen if you read first the TMR1L register.
To avoid this problem, there are two methods to follow. The first method is to shut down the Timer1 module (BCF T1CON,TMR1ON), get the reading and then re-enable the module (BSF T1CON,TMR1ON). Many times this is not possible. Especially when the pulses to be counted have high frequency, and a 4-cycles operation will have a significant change in the result. If the turn-off/on operation is not possible, then you should follow the test-method.
With the test-method, you read and save first the TMR1H register then you read and save the TMR1L register. Then, you re-read the TMR1H register and test this value with the previous-read value. If these two values are not equal, then it means that either the TMR1L has overflow, or the TMR1H AND TMR1L have overflow. Either way, you re-read and re-save the TMR1H and TMR1L register. The following code is supplied from Microchip as a fail-safe read operation for the Timer1 register:
; All interrupts are disabled MOVF TMR1H, W ; Read high byte MOVWF TMR1_H_Buffer ; Save this value MOVF TMR1L, W ; Read low byte MOVWF TMR1_L_Buffer ; Save this value MOVF TMR1H, W ; Re-Read high byte SUBWF TMR1_H_Buffer, W ; Sub 1st read with 2nd read BTFSC STATUS, Z ; Is result = 0 GOTO CONTINUE ; No overflow occurred ; Else, an overflow has occurred ; Reading the high and low bytes now will read a good value. MOVF TMR1H, W ; Read high byte MOVWF TMR1_H_Buffer ; Save this value MOVF TMR1L, W ; Read low byte MOVWF TMR1_L_Buffer ; Save this value ; Re-enable the Interrupt (if required) CONTINUE ; Continue with your code
During the writing operations, all you need to do is to turn off the Timer1 module, write the new values and then turn it on back again. Alternatively, you can clear the TMR1L register to avoid an overflow, then write the new value to TMR1H, and finally write the new value to TMR1L register. The following code is supplied from Microchip as a fail-safe write operation for the Timer1 register:
; All interrupts are disabled CLRF TMR1L ; Clear Low byte, Ensures no rollover into TMR1H MOVLW NEW_H_BYTE ; New value for TMR1H MOVWF TMR1H, F ; Write to High byte MOVLW LEW_L_BYTE ; New value for TMR1L MOVWF TMR1H, F ; Write Low byte ; Re-enable the Interrupt (if required) ; Continue with your code
Examples with the Timer1 Module
For the sake of understanding, find below some examples on how to setup the TMR1 module.
Example 1 - TMR1 increasing on every LOW to HIGH transition on T1CKI pin synchronized
BCF T1CON,5 ; BCF T1CON,4 ; Prescaler ratio = 1:1 BCF T1CON,T1OSCEN ; Timer1 Oscillator is disabled BCF T1CON,T1SYNC ; Enable the synchronization module BSF T1CON,TMR1CS ; Timer1 count source from RB6/T1CKI BSF T1CON,TMR1ON ; Enable Timer1 Module
Example 2 - TMR1 measures input pulses on T1CKI pin (NOT synchronized), divided by 4
BSF T1CON,5 ; BCF T1CON,4 ; Prescaler ratio = 1:4 BCF T1CON,T1OSCEN ; Timer1 Oscillator is disabled BSF T1CON,T1SYNC ; Disable the synchronization module BSF T1CON,TMR1CS ; Timer1 count source from RB6/T1CKI BSF T1CON,TMR1ON ; Enable Timer1 Module
Confirm your knowledge
There is an online test to check your knowledge on this page. You may reveal the test with the following button:
No part of this publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning or otherwise without the prior written permission of the author.
Read the Disclaimer
All trademarks used are properties of their respective owners.
Copyright © 2007-2009 Lazaridis Giorgos.
All rights reserved.