Sie sind auf Seite 1von 29

ECE 3730 Principles of Embedded Systems: The PIC16F877A Timer2 Module

The Timer2 Module of the PIC16F877A

Overview of the Timer2 Module


Timer2 Configuration Processor Read/Write CLK Counter RollOver Flag (TMR2IF) Interrupt Logic

Timer2 Module

The Timer2 module can be modeled by a configurable counter and a flag. The processor (your program) configures the Timer2 for a desired amount of time. When the counter rolls over, the roll-over bit changes from 0 to 1, and sets a flag The counter is then reset and resumes to count. The processor can poll the flag, or, optionally, when the flag is set, an interrupt can be signaled to the processor.

Overview of the Timer2 Module


Timer2 Configuration Processor Read/Write CLK Counter RollOver Flag (TMR2IF) Interrupt Logic

Timer2 Module

The number of clock (CLK) edges required to make the counter roll over is configurable, and is given by the product of 3 individual counters: NumClockEdges = Pre-scalar * PR2 * Post-scalar

The time at which the counter rolls over is given by (Period of CLK) * NumClockEdges (Period of CLK) * Pre-scalar * PR2 * Post-scalar
3

Implementation of Timer2 Module


(CLK) FOSC/4
RollOver RollOver

Pre-scalar Counter 1, 4, 16

Timer2 Counter
EX

Post-scalar Counter 116


TMR2IE

Set Flag TMR2IF

Comparator

PR2 Register

Interrupt Logic

FOSC is the frequency of the chip oscillator. We use ~4 MHz. FOSC is divided by 4, and the result clocks the Timer2 module: CLK FREQUENCY = FOSC/4 Time to execute one instruction: TCYC = (FOSC/4)-1
4

Implementation of Timer2 Module


(CLK) FOSC/4
RollOver RollOver

Pre-scalar Counter 1, 4, 16

Timer2 Counter
EX

Post-scalar Counter 116


TMR2IE

Set Flag TMR2IF

Comparator

PR2 Register

Interrupt Logic

The Pre-scalar is configurable to rollover at either 1, 4, or 16 cycles of the CLK (FOSC/4) Configuration of the Pre-scalar counter is done by writing to bits T2CKPS1:T2CKPS0 of the TMR2 control register (T2CON).

Implementation of Timer2 Module


(CLK) FOSC/4
RollOver RollOver

Pre-scalar Counter 1, 4, 16

Timer2 Counter
EX

Post-scalar Counter 116


TMR2IE

Set Flag TMR2IF

Comparator

PR2 Register

Interrupt Logic

Each time the Pre-scalar counter rolls-over, this increments the Timer2 Counter. When (and each time) the Timer2 Counter exceeds (EX) (one more than) the PR2 register, the Post-scalar Counter is incremented, and Timer2 Counter is reset. The PR2 register is an 8-bit register, which is writable. NOTE: PR2=0 means 1, PR2=1 means 2, , PR2=255 means 256
6

Implementation of Timer2 Module


(CLK) FOSC/4
RollOver RollOver

Pre-scalar Counter 1, 4, 16

Timer2 Counter
EX

Post-scalar Counter 116


TMR2IE

Set Flag TMR2IF

Comparator

PR2 Register

Interrupt Logic

The Post-scalar counter is configurable to roll-over at 1 to 16 cycles of the EX signal


Configuration of the Post-scalar counter is done by writing to bits TOUTPS3:TOUTPS0 of the TMR2 control register (T2CON).
7

Implementation of Timer2 Module


(CLK) FOSC/4
RollOver RollOver

Pre-scalar Counter 1, 4, 16

Timer2 Counter
EX

Post-scalar Counter 116


TMR2IE

Set Flag TMR2IF

Comparator

PR2 Register

Interrupt Logic

When the Post-scalar counter rolls over, the TMR2IF is set. Optionally, if the TiMeR2 Interrupt Enable (TMR2IE) bit is set, the TMR2IF may be relayed to the interrupt logic of the processor.

Testing Timer2
Testing Various Time Intervals Using Polling
Enter main() Function
PIC Processor Oscilloscope
1ms

PIR Register

Initialize Port Pin RE2 (Visualization) Initialize Timer2 Various Intervals

RE2

Probe (+ve)
1ms

GND Probe (-ve)

TMR2IF

Timer2 Counter Visualization Pin is Bit-2 of PortE (RE2) Timer2 module sets the TMR2IF flag at various intervals

Start Timer2

TMR2IF=1 ? Y TMR2IF=0

Wait for flag to become set

Toggle Visualization Pin

while(1) { while(TMR2IF==0); TMR2IF = 0; RE2 = !RE2; }


9

Timer 2 Unit Test


Experimental Setup for Testing Timer2
VDD (5 V) VSS (GND) Programming Data Programming Clock 10 F

40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21

RJ-12

PIC16F877A
1 Master Clear 10 k 3.3 k 33 pF 2 3 4 5 6 7 8 RE2 9 10 11 12 13 14 15 16 17 18 19 20

VDD (5 V) VSS (GND)

To Oscilloscope
10

Testing Timer2
Testing Various Time Intervals Using Polling Desired Period 890 ns 40 s 80 s 500 s 1 ms 58 ms TCYC 890 ns 890 ns 890 ns 890 ns 890 ns 890 ns PreScalar 1 1 1 1 1 16 PR2 1 3 6 51 75 256 PostScalar 1 15 15 11 15 16 Calculated Period .89 s 40.05 s 80.1 s 499.29 s 1,001.25 s 58,327.04 s

Desired Period = (Period of FOSC/4) x Pre-scalar x PR2 x Post-scalar For 40 s: = 890 x 10-9 = 40.05 x 10-6 x 1 x 3 x 15

Inconvenient to hand calculate the best combination of Pre-scalar, PR2, and Postscalar for a desired period that yields the least error. Solve the problem programmatically
11

TIMER2 POLLING: INITIALIZATION


Timer2Initialization.c #include <xc.h> void timer2Init(void) { INTCON = 0; // T2CON = 0b01110000; PR2 = 2; // TMR2ON = 1; // // can also do in T2CON TMR2IF = 0; // }

Disable all interrupts. 1 s * 1 * 3 * 15 = 40 ms Switch Timer2 on = 0b01110100 Clear Timer2 flag

12

V1: POLLING
Complete Project Source Code (Unit Testing)
Main.c #include <xc.h> // pic16f877a.h #include "ProcessorConfiguration.h" #include "functionPrototypes.h" void main(void) { portInit(); timer2Init(); while(1) { while(TMR2IF == 0){} TMR2IF = 0; RE2 = !RE2; } } Timer2Initialization.c #include <xc.h> void timer2Init(void) { INTCON = 0; // Disable all interrupts. T2CON = 0b01110000; PR2 = 2; // 1 s * 1 * 3* 15 = 40 ms TMR2ON = 1; // Switch Timer 2 on // can also do T2CON = 0b01110100 TMR2IF = 0; // Clear Timer2 flag } PortInitialization.c #include <xc.h> // pic16f877a.h

void portInit(void) { PCFG3 = 0; // Configure PORTE as digital I/O PCFG2 = 1; PCFG1 = 1; TRISE2 = 0; // Configure PORTE-2 as output } FunctionPrototypes.h void main(void); void timer2Init(void); void portInit(void); ProcessorConfiguration.h #pragma config BOREN = OFF, CPD = OFF, DEBUG = ON, WRT = OFF, FOSC = EXTRC, WDTE = OFF, CP = OFF, LVP = OFF, PWRTE = OFF // Set configuration bits (See pic16f877a.h)

13

PROBLEMS
When viewing the visualization pin on the oscilloscope we observed some unequal periods and erratic behavior For very small periods, the waveform was not a perfect square wave, as expected To discover the problem, we analyzed the code and implemented a more accurate clock Using a 4MHz crystal, we obtained an instruction period of exactly 1 s.

14

Timer 2 Unit Test


Experimental Setup with 4 MHz Crystal
VDD (5 V) VSS (GND) Programming Data Programming Clock 10 F

40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21

RJ-12

PIC16F877A
1 Master Clear 10 k 2 3 4 5 6 7 8 RE2 9 10 11 12 13 14 15 16 17 18 19 20

4MHz
22 pF 22 pF

VDD (5 V) VSS (GND)

To Oscilloscope

A 4MHz crystal oscillator was used to obtain a more accurate clock

15

ANALYSIS OF CODE
DISSASEMBLED VERSION OF while(1) LOOP
! while(1) { 0x7FC: GOTO 0x7F2 ! while(TMR2IF == 0); 0x7F1: GOTO 0x7F2 0x7F2: BCF STATUS, 0x5 0x7F3: BCF STATUS, 0x6 0x7F4: BTFSS PIR1, 0x1 0x7F5: GOTO 0x7F7 0x7F6: GOTO 0x7F8 0x7F7: GOTO 0x7F2 ! TMR2IF = 0; 0x7F8: BCF PIR1, 0x1 ! RE2 = !RE2; 0x7F9: MOVLW 0x4 0x7FA: XORWF PORTE, F 0x7FB: GOTO 0x7F2 ! } while(1) { while(TMR2IF==0); TMR2IF = 0; RE2 = !RE2; } Compiler inefficiencies:
GOTO 0x7F2 ? BCF STATUS, 0x5 BCF STATUS, 0x6 ? GOTO 0x7F7 GOTO 0x7F2 ? GOTO 0x7F8 ? MOVLW 0x4 ?
16

BEST CASE EXECUTION TIME


! while(1) { 0x7FC: GOTO 0x7F2 ! while(TMR2IF == 0); 0x7F1: GOTO 0x7F2 0x7F2: BCF STATUS, 0x5 0x7F3: BCF STATUS, 0x6 0x7F4: BTFSS PIR1, 0x1 0x7F5: GOTO 0x7F7 0x7F6: GOTO 0x7F8 0x7F7: GOTO 0x7F2 ! TMR2IF = 0; 0x7F8: BCF PIR1, 0x1 ! RE2 = !RE2; 0x7F9: MOVLW 0x4 0x7FA: XORWF PORTE, F 0x7FB: GOTO 0x7F2 ! }

BestcasewhenTMR2IFissetat thebeginningofBTFSSPIR1,0x1 11InstructionCycles: 1:BTFSSPIR1,0x1 1:NOP 2:GOTO0x7F8 1:BCFPIR1,0x1 1:MOVLW0x4 1:XORWFPORTE,F 2:GOTO0x7F2 1:BCFSTATUS,0x5 1:BCFSTATUS,0x6

17

WORST CASE EXECUTION TIME


! while(1) { 0x7FC: GOTO 0x7F2 ! while(TMR2IF == 0); 0x7F1: GOTO 0x7F2 0x7F2: BCF STATUS, 0x5 0x7F3: BCF STATUS, 0x6 0x7F4: BTFSS PIR1, 0x1 0x7F5: GOTO 0x7F7 0x7F6: GOTO 0x7F8 0x7F7: GOTO 0x7F2 ! TMR2IF = 0; 0x7F8: BCF PIR1, 0x1 ! RE2 = !RE2; 0x7F9: MOVLW 0x4 0x7FA: XORWF PORTE, F 0x7FB: GOTO 0x7F2 ! }

WorstcasewhenTMR2IFisset whenBTFSSPIR1,0x1completes
18InstructionCycles: 1:BTFSSPIR1,0x1 2:GOTO0x7F7 2:GOTO0x7F2 1:BCFSTATUS,0x5 1:BCFSTATUS,0x6 1:BTFSSPIR1,0x1 1:NOP 2:GOTO0x7F8 1:BCFPIR1,0x1 1:MOVLW0x4 1:XORWFPORTE,F 2:GOTO0x7F2 1:BCFSTATUS,0x5 1:BCFSTATUS,0x6

18

OPTIMIZED VERSION OF while(1) LOOP


movlw 0b00000100; while(1) { while(TMR2IF==0); L1: btfss PIR1, 0x1; goto L1; bcf PIR1, 1; xorwf PORTE, F; goto L1;
19

TMR2IF = 0; RE2 = !RE2; }

BEST CASE OF OPTIMIZED VERSION


movlw 0b00000100; BestcasewhenTMR2IFissetat thebeginningofBTFSSPIR1,0x1 6InstructionCycles: 1:BTFSS PIR1, 0x1 1:NOP 1:BCFPIR1, 1 1:XORWF PORTE, F 2:GOTO L1
20

L1: BTFSS PIR1, 0x1; GOTO L1; BCF PIR1, 1;

XORWF PORTE, F; GOTO L1;

WORST CASE OF OPTIMIZED VERSION


movlw 0b00000100; WorstcasewhenTMR2IFisset whenBTFSSPIR1,0x1completes 9InstructionCycles: 1:BTFSS PIR1, 0x1 2:GOTO L1 1:BTFSS PIR1, 0x1 1:NOP 1:BCFPIR1, 1 1:XORWF PORTE, F 2:GOTO L1
21

L1: BTFSS PIR1, 0x1; GOTO L1; BCF PIR1, 1;

XORWF PORTE, F; GOTO L1;

RESULTS OPTIMIZED ASSEMBLY


Pre-scaler = 1, Post-scalar = 1
L1: btfss goto bcf xorwf goto PIR1, 0x1; L1; PIR1, 1; PORTE, F; L1;

btfss is FALSE

ACTUAL TIMER2 ROLLOVER POINTS

L1: btfss nop; bcf xorwf goto

PIR1,

0x1;

PIR1, 1; PORTE, F; L1;

PR2 = 5 Expected Period: 12s

btfss is TRUE
22

RESULTS OPTIMIZED ASSEMBLY


Pre-scaler = 1, Post-scalar = 1
L1: btfss goto bcf xorwf goto PIR1, 0x1; L1; PIR1, 1; PORTE, F; L1;

btfss is FALSE

ACTUAL TIMER2 ROLLOVER POINTS

L1: btfss nop; bcf xorwf goto

PIR1,

0x1;

PIR1, 1; PORTE, F; L1;

PR2 = 4 Expected Period: 10s

btfss is TRUE
23

RESULTS OPTIMIZED ASSEMBLY


Pre-scaler = 1, Post-scalar = 1
L1: btfss goto bcf xorwf goto PIR1, 0x1; L1; PIR1, 1; PORTE, F; L1;

btfss is FALSE

ACTUAL TIMER2 ROLLOVER POINTS

L1: btfss nop; bcf xorwf goto

PIR1,

0x1;

PIR1, 1; PORTE, F; L1;

PR2 = 6 Expected Period: 14s

btfss is TRUE
24

INTERRUPT METHOD
Interrupt method would produce a better waveform, because the system will be synchronized with each TMR2IF becoming set Disadvantage of the interrupt method is the interrupt latency cause by saving the status of the machine upon an interrupt

25

TIMER2 INTERRUPTS: INITIALIZATION


Timer2Initialization.c #include <xc.h> void timer2Init(void) { INTCON = 0; // Disable all interrupts. T2CON = 0b01110100; PR2 = 2; // 1 s * 1 * 3 * 15 = 40 s TMR2IE = 1; // Enable TMR2 interrupts (PIE1<1>) PEIE = 1; // Enable peripheral interrupts (INTCON<6>) GIE = 1; // global interrupt enable (INTCON<7>) TMR2IF = 0; // Clear Timer2 flag (PIR1<1>) }
26

INTERRUPT LOGIC

TMR2IE = 1; PEIE = 1; GIE = 1; TMR2IF = 0;


27

INTERRUPT FUNCTION
Main.c ... REQUIRED SYNTAX GOOD PROGRAMMING PRACTISE

void interrupt TMR2InterruptFunction(void) { if(TMR2IF==1) //Check if this is a TMR2 interrupt { TMR2IF = 0; //Clear TMR2IF RE2 = !RE2; //Toggle visualization bit } return; //Return from interrupt }
28

V1: INTERRUPTS
Complete Project Source Code (Unit Testing)
Main.c #include <xc.h> // pic16f877a.h #include "ProcessorConfiguration.h" #include "functionPrototypes.h" unsigned char timeOut = 0; void main(void) { portInit(); timer2Init(); while(1) { } } void interrupt TMR2InterruptFunction(void) { if(TMR2IF==1) { TMR2IF = 0; RE2 = !RE2; } return; } Timer2Initialization.c #include <xc.h> void timer2Init(void) { INTCON = 0; // Disable all interrupts. T2CON = 0b01110100; PR2 = 2; // 1 s * 1 * 3* 15 = 40 ms TMR2IE = 1; // Enable TMR2 interrupts PEIE = 1; // Enable peripheral interrupts GIE = 1; // global interrupt enable TMR2IF = 0; // Clear Timer2 flag } PortInitialization.c (same as for polling) FunctionPrototypes.h (same as for polling) ProcessorConfiguration.h (same as for polling)

29