Assignment title: Information
51
6 Lab 6 – Timer1 Module
6.1 Aim
This laboratory practical will introduce you to the Timer1 module which is one of three timer/counter
peripherals located on the PIC16F877A MCU. The practical exercises will focus on the proper
configuration and usage of the Timer1 module in timer mode only.
6.2 Learning Outcomes
After this laboratory practical you will:
• Understand the structure of the Timer1 module on the PIC16F877A.
• Be able to configure the Timer1 module using the appropriate special function registers.
• Be able to develop projects to utilise the Timer1 module in a range of applications.
6.3 Background
6.3.1 Introduction
Timer1 is one of three timer modules on board the PIC16F877A MCU. It is a 16 bit timer meaning that
it is capable storing a maximum of 2 65536 16 = counts per overflow. Compare this to the 8 bit Timer0
module which can only provide 2 256 8 = counts per overflow.
Figure 6-1 Timer 1 module block diagram
Figure 6-1 shows block diagram representation of the Timer1 module. Timer1 has shares several
similar features with Timer0. There is a prescaler available for use, however the maximum divide down
ratio is 1:8 (compared with a maximum of 1:256 for Timer0). There is also a Timer1 overflow interrupt
which utilises the TMR1IE and TMR1IF bits that can be found in the PIE1 and PIR1 registers
respectively. TMR1IF can be polled to check for the occurrence of Timer1 overflows. The process for
doing this is similar to that used in Lab 4, where TMR0IF bit was polled to check for a Timer0 overflow.
The Timer1 module can act as a counter whereby the count value increases with every occurrence of
a rising edge of an external clock input supplied to pin connected to PORTC bit 0 (RC0). There is also
an option to connect a low frequency crystal oscillator to provide a lower power timer facility that
continues to operate even when the MCU is in sleep mode.
In this laboratory practical we will be considering the use of the Timer1 module in timer mode only.
In this case the count value is continuously updated at the instruction clock rate, f f CY OSC = / 4. As 52
such, the formulae for calculating count intervals and overflow periods are exactly the same as for
Timer0, except for the changes available prescaler ratios and the larger maximum count capacity,
which is now 65536.
4 prescaler 1count
delay
osc
TMR
f
´ ´
=
delay
1count
4 prescaler
fosc
TMR = ´
´
6.3.2 Timer1 configuration
The configuration bits relating to the Timer1 module can be found in the T1CON (Timer1 CONtrol)
register (see figure 6-2).
Figure 6-2 T1CON register bits
To use the clock as a timer sourced from the internal instruction clock the TMR1CS bit needs to be set
to zero. It is also necessary to configure the prescaler using the T1CKPS bitfield. Finally, the timer must
be started by setting the TMR1ON bit. All other bits can safely assume a 'don't care' state and thus
may be set to zero. Note that bits 6 and 7 are unused and can be set to zero in the interests of
consistency.
Table 6-1 Prescaler configuration
T1CKPS1:T1CKPS0 Bitfield Value TMR1 Rate
00 0 1:1
01 1 1:2
10 2 1:4
11 3 1:853
Table 6-2 TIMER1CON summary of bit configuration
Bit Name Bit location in
T1CON
MPLAB XC8 syntax Configuration requirements
T1CKPS1:0 5:4 T1CONbits.T1CKPS Define as required by application
T1OSCEN 3 T1CONbits.T1OSCEN No effect in timer mode (don't care state)
T1SYNC 2 T1CONbits.T1SYNC No effect in timer mode (don't care state)
TMR1CS 1 T1CONbits.TMR1CS Set to 0 to enable internal clock source
(timer mode)
TMR1ON 0 T1CONbits.TMR1ON Set to 1 to enable timer
To summarise, the bitwise configuration of T1CON (see figure 6-2) for the operation of timer 1 in timer
mode may be considered as follows:
T1CON = XXUU XX0U
where X = a 'don't care' state and U = a user defined state.
For instance to set up Timer1 to provide a prescaler value of 1:4 we need to write the following to
value to T1CON (all don't care states are set to zero here),
T1CON = 0010 0000 = 0x20
In this instance the Timer1 module is configured but still currently disabled (turned off).
6.3.3 Timer1 preload calculation
Remember that the maximum number of counts the 16 bit Timer1 module can make before
overflowing is 65536.
For example, if a 100 ms delay is required, with the prescaler divide down ratio set to 1:8, then the
required number of TMR1 counts is as follows.
delay 100 10 3.2768 10 3 6
1count 10240
4 prescaler 4 8
fosc
TMR
-
´ ´ ´ ´
= = =
´ ´
When 10240 counts of the Timer1 module have occurred, we know that 100 ms have elapsed. If we
are going to use the overflow polling to measure the delay, then the preload value required is then
simply
preload 65536 TMR1count = -
which for the example cited above equates to a preload value of 55296.
6.3.4 Procedure for loading Timer 1
Timer1 is a 16 bit timer module which means it requires 16 bits to store its count value. However,
because the PIC16f877A MCU has an 8-bitarchitecture, the maximum data register width is only 8 bits 54
(1 byte) wide. This means that two SFRs are required to hold the 16 bit count value. These are
separated into the high (TMR1H) and low (TMR1L) bytes, which must be loaded individually. Timer1
should be disabled to this two stage load process to ensure proper operation. The procedure is as
follows:
Convert the required preload value into hexadecimal.
Turn Timer1 OFF (T1CONbits.TMR1ON=0).
Take the leftmost two digits (most significant byte) and load into the TMR1H SFR.
Take the rightmost two digits (least significant byte) and load that value into the TMR1L SFR.
Turn Timer1 ON (T1CONbits.TMR1ON=1).
For a preload value of 55296 (see section 6.3.3) the hexadecimal notation is 0xD800. So we can write
the following code to load Timer1:
T1CONbits.TMR1ON = 0; // Turn Timer 1 OFF
TMR1H = 0xD8; // Load high byte
TMR1L = 0x00; // Load low byte
T1CONbits.TMR1ON = 1; // Turn Timer 1 ON
6.4 Procedure
6.4.1 Exercise 1 – Simple Timer1 delay example
Create a new project in the MPLAB X IDE, create an empty source file, and populate it with
the following code listing.
// Filename: Lab6Ex1.c
// Version: 1.0
// Date:
// Author:
//
// Description: Implementing a Timer1 delay
#include // Required for all MPLAB XC8 source files
void main(void)
{
TRISB = 0x00; // Configure PORTB
PORTB = 0x00;
T1CON = 0x30; // Timer1 OFF, Prescaler 1:8
while(1)
{
T1CONbits.TMR1ON = 0; // Turn Timer 1 OFF
TMR1H = 0x9C; // Load high byte
TMR1L = 0x00; // Load low byte
T1CONbits.TMR1ON = 1; // Turn Timer 1 ON
while(!PIR1bits.TMR1IF); // Delay
PORTB++;
PIR1bits.TMR1IF = 0; // Clear overflow flag
}
}55
Build the project and upload the HEX file onto the PIC16F877A MCU.
Study the code listing carefully and observe what is happening. Comment on the operation
of the code, how is the delay being implemented? Calculate the delay time created using the
Timer1 preload value in the example code.
Confirm the result of your calculation by measuring the total time for PORTB to count up to
256 in binary and then dividing that value accordingly to get the duration for a single count.
Look through the PIC16F877A datasheet and locate the section describing the contents of the
PIR1 SFR. Copy the information into your logbook and note the location of the Timer1
overflow interrupt flag in the SFR.
Calculate the maximum delay possible using a single overflow of Timer1 assuming an
oscillator frequency of 3.2768 MHz.
6.4.2 Exercise 2 – Creating a short delay using Timer1
Calculate the parameters required to create a 1 second delay using Timer 0. You should
determine a suitable preload value which, when combined with an integer number of
overflows, will produce the required delay.
Create a new project in the MPLABX IDE and develop a configurable function which has a
single parameter that determines the integer number of seconds delay invoked. The function
prototype should have the following form:
void Timer1Delay(unsigned char);
The delay must be implemented using Timer1. You may find it useful to review your solution
to section 4.4.4 in which you completed a similar exercise involving the creation of a
configurable delay function using Timer0. In addition, the flowchart shown in figure 6-3 may
be a useful aid to help you develop your code.
Configure T1CON
Start
TMR1IF==1?
Finish
Configure Ports
Start
Timer1Delay()
Toggle LED
NO
YES
while
YES
NO56
Figure 6-3 Flowchart showing one possible implementation for the Timer1Delay() function
6.4.3 Exercise 3 – Validating the operation of your Timer1 delay function
Validate the operation of your new function by creating suitable test code which calls the
function and measure the delays created. To achieve this, the test code should toggle an LED
of your choice on one of the E-Block boards.
The implementation of your code should be similar to that shown in figure 6-4. The flowchart
symbol denotes a subroutine (function) call. In this case it represents a call to the
function you developed in the previous exercise. The symbol is a display symbol
which represents the display of information to the user. In this case the toggling of the LED is
considered to be the information. Writing output to the LCD would be another example of a
display process.
Figure 6-4 Flowchart for Timer1Delay() function testing
Confirm that the function works correctly for delays of 1, 2 and 5 second delays. Make sure
you provide evidence of the results in your logbook.
6.4.4 Exercise 4 – Applying a configurable delay function to create a simple stopwatch
The aim of this exercise is to develop create a simple stopwatch using the LCD and the
configurable delay function you developed in the previous exercise.
Create a new project in the MPLAB X IDE. The project should be developed to provide the
following functionality:
• Display on the LCD an elapsed time in the form mm:ss where mm and ss are the current
count in minutes and seconds respectively.
• The elapsed time displayed on the LCD should update automatically once per second.
Start the design process by developing a flow chart. It may take a few iterations to come up
with a suitable design. Upload the following HEX file to the MCU to observe the correct
operation of your code:
J:/Embedded Systems/MPLAB/Examples/SimpleStopwatch.hex
Configure T1CON
Start
TMR1IF==0?
Finish
Configure Ports
Start
Timer1Delay()
Toggle LED
YES
NO
while(1) loop
Configure Ports
Start
Timer1Delay()
Toggle LED
Timer1Delay()
Toggle LED
O
while(1) loop
Configure T1CON
Start
TMR1IF==1?
Finish
Configure Ports
Start
Timer1Delay()
Toggle LED
Timer1Delay()
Toggle LED
NO
YES
while(1) loop
YES
NO57
6.4.5 Exercise 5 – Adding functionality to the stopwatch
Create another new project in MPLAB X and further develop the code created in section 6.4.4
to add the following functionality:
• The initial state of the stopwatch when the code executes should be displaying 00:00 and
be stopped.
• The operation of the stopwatch is toggled by pressing RD0. Pressing RD0 once will start
the stopwatch. Pressing RD0 a second time will stop operation. This operation should be
repeatable.
• The stopwatch can be reset at any time to pressing the switch connected to RD1. Once
reset the stopwatch should revert to the initial state i.e. stopped and displaying 00:00.